标签:using 作用 mod 答案 div memset 暴力 开始 数加
题意:给你一个无向图,问图中有多少个符合条件的集合?条件为这个集合里面存在一个子集(大小>=3)为团或者都是孤立点。答案mod1e9+7;
根据 Ramsey定理,大于等于6个的集合,肯定存在一个子集的边都是红色或者都是蓝色,即为团还是为孤立点;
所以当n大于等于6的时候,所有的取6个或六个以上的子集的集合都是符合的,所以将这些排列组合的方式全部都计算在内;
即C(n,i) i的取值范围为(6~n) 但是这样子算会超时,我们可以计算C(n,i) i从0开始计算,这样子所有的数加起来,就是2^n
然后再减去C(n,i)i从0到5即可;
n的取值范围到50,所以暴力不超时;
然后还剩下点集为3到5的情况,这个时候,我们就分别枚举点集为3,4,5,判断是否满足情况即可(题目给出的m条边就在这个时候起作用)
只要满足图中有3个为孤立点即可;
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int M = 1e2+7; 5 const LL mod = 1e9+7; 6 int ncase,n,m,cas=1; 7 int vis[M][M]; 8 LL fac[M]; 9 void init() 10 { ///预处理阶乘 11 fac[0]=1;fac[1]=1; 12 for (int i=2;i<M;i++) 13 fac[i]=fac[i-1]*i%mod; 14 } 15 LL quick_pow(LL p,LL k) ///快速幂 16 { 17 LL res=1,tp=p; 18 if(k<0) return 0; 19 while(k){ 20 if(k&1) res=res*tp%mod; 21 tp=tp*tp%mod; 22 k>>=1; 23 } 24 return res; 25 } 26 LL C(int n,int m) 27 { 28 return fac[n]*quick_pow(fac[m],mod-2)%mod*quick_pow(fac[n-m],mod-2)%mod; 29 }///费马小定理求逆元+快速幂 30 int judge(int i,int j,int k){ ///判断三点之间满不满足不稳定点集 31 if(vis[i][j]&&vis[i][k]&&vis[j][k]) return 1;///三点之间相连 32 if(!vis[i][j]&&!vis[i][k]&&!vis[j][k]) return 1; ///三点之间不互联 33 return 0; 34 } 35 int judge1(int i,int j,int k,int l) 36 { 37 if(judge(i,j,k)||judge(i,j,l)||judge(j,k,l)||judge(i,k,l)) return 1; ///表示4个点中有三个点为不稳定点集就行,为什么呢? 38 ///因为时题目要求的,不稳定点集为3个点。 39 return 0; 40 } 41 int judge2(int i,int j,int k,int l,int o){ 42 ///表示5个点中有4个点满足就行 43 if(judge1(i,j,k,l)||judge1(i,j,k,o)||judge1(i,j,l,o)||judge1(j,k,l,o)||judge1(i,k,l,o)) return 1; 44 return 0; 45 } 46 47 int main(){ 48 49 init(); 50 scanf("%d",&ncase); 51 while(ncase--){ 52 scanf("%d%d",&n,&m); 53 memset(vis,false,sizeof(vis)); 54 for(int i=1;i<=m;i++){ 55 int u,v; 56 scanf("%d%d",&u,&v); 57 vis[u][v]=vis[v][u]=1; 58 } 59 LL ans=0; 60 if(n>=6){ 61 ans=(ans+quick_pow(2,n))%mod; ///多项式定理C(n,0)+C(n,1)+...+C(n,n)=2^n 62 ///C(n,k)(k>=6)表示,从n个中取k个出来,总存在一个不稳定点集的个数(三点之间互联或三点之间不连) 63 for(int i=0;i<6;i++) ///减去前5个 64 ans=(ans-C(n,i)+mod)%mod; 65 } 66 if(n>=3){ ///暴力取3个 67 for(int i=1;i<=n;i++) 68 for(int j=i+1;j<=n;j++) 69 for(int k=j+1;k<=n;k++) 70 if(judge(i,j,k)) ans=(ans+1)%mod; 71 } 72 if(n>=4){ ///暴力取4个 73 for(int i=1;i<=n;i++) 74 for(int j=i+1;j<=n;j++) 75 for(int k=j+1;k<=n;k++) 76 for(int l=k+1;l<=n;l++) 77 if(judge1(i,j,k,l)) ans=(ans+1)%mod; 78 } 79 if(n>=5){ ///暴力取5个 80 for(int i=1;i<=n;i++) 81 for(int j=i+1;j<=n;j++) 82 for(int k=j+1;k<=n;k++) 83 for(int l=k+1;l<=n;l++) 84 for(int o=l+1;o<=n;o++) 85 if(judge2(i,j,k,l,o)) ans=(ans+1)%mod; 86 } 87 printf("Case #%d: %lld\n",cas++,ans); 88 } 89 return 0;}
标签:using 作用 mod 答案 div memset 暴力 开始 数加
原文地址:https://www.cnblogs.com/pangbi/p/12341021.html