码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5917

时间:2020-02-21 14:25:33      阅读:69      评论:0      收藏:0      [点我收藏+]

标签: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;}

 

hdu 5917

标签:using   作用   mod   答案   div   memset   暴力   开始   数加   

原文地址:https://www.cnblogs.com/pangbi/p/12341021.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!