• ccpc 长春站 G


    题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=5917]

    题意:

    给你一个无向图,问图中有多少个符合条件的集合?条件为这个集合里面存在一个子集(大小>=3),其中任意两个点之间相连或者都是孤立点。答案mod 1e9+7。
    

    思路:

    • 先知道一个定理:Ramsey定理
      该定理简述为:6 个人中至少存在3人相互认识或者相互不认识。
      该定理等价于证明这6个顶点的完全图的边,用红、蓝二色任意着色,必然至少存在一个红色边三角形,或蓝色边三角形
      即:只要一个集合中有大于等于6个点,则一定符合条件
      所以对集合大小大于6的部分直接求
    • 小于6的部分暴力求解,n<=50,写5重循环也是不会超时的

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<sstream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<cstdlib>
    #include<cmath>
    using namespace std;
    #define re register int
    #define ull unsigned long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define N 100010
    #define lson rt<<1
    #define rson rt<<1|1
    #define mo 1000000007
    #define lowbit(x) (x)&(-(x))
    void FRE(){freopen("subsets.in","r",stdin);freopen("subsets.out","w",stdout);}
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ll)(ch-'0');ch=getchar();}
        return x*f;
    }
    ll ans;
    int g[105][105],n,T,m;
    ll ksm(ll a,ll b)
    {
    	ll tmp=1;
    	while(b)
    	{
    		if (b&1) tmp=(tmp*a)%mo;
    		b>>=1;
    		a=(a*a)%mo;
    	}
    	return tmp;
    }
    ll niyuan(ll x)
    {
    	return ksm(x,mo-2);
    }
    ll C(int n,int m)
    {
    	ll tmp=1;
    	for (ll i=1;i<=m;i++)
    	{
    		tmp=(tmp*(n-m+i)%mo)%mo;
    		tmp=(tmp*niyuan(i)%mo)%mo;
    	}
    	return tmp;
    }
    bool OK(int i,int j,int k)
    {
    	if (g[i][j]&&g[i][k]&&g[j][k]) return true;
    	if (g[i][j]+g[i][k]+g[j][k]==0) return true;
    	return false;
    }
    bool OK2(int i,int j,int k,int p)
    {
    	if (OK(i,j,k)||OK(i,j,p)||OK(j,k,p)||OK(i,k,p))
    		return true;
    	return false;
    }
    bool OK3(int i,int j,int k,int p,int pp)
    {
    	if (OK2(i,j,k,p)||OK2(i,j,k,pp)||OK2(i,k,p,pp)||OK2(j,k,p,pp)||OK2(i,j,p,pp))
    		return true;
    	return false;
    }
    int main()
    {
    	T=read();
    	for (int tt=1;tt<=T;tt++)
    	{
    		memset(g,0,sizeof(g));ans=0;
    		n=read(),m=read();
    		while (m--)
    		{
    			int x=read(),y=read();
    			g[x][y]=g[y][x]=1;
    		}
    		if (n>=6) 
    		{
    			ans=ksm(2,n);
    			for (int i=0;i<=5;i++)
    				ans=(ans-C(n,i)+mo)%mo;
    		}
    		if (n>=3)
    		{
    			for (int i=1;i<=n;i++)
    				for (int j=i+1;j<=n;j++)
    					for (int k=j+1;k<=n;k++)
    					if (OK(i,j,k)) ans=(ans+1)%mo;
    		}
    		if (n>=4)
    		{
    			for (int i=1;i<=n;i++)
    				for (int j=i+1;j<=n;j++)
    					for (int k=j+1;k<=n;k++)
    						for (int p=k+1;p<=n;p++)
    						if (OK2(i,j,k,p)) ans=(ans+1)%mo;
    		}
    		if (n>=5)
    		{
    			for (int i=1;i<=n;i++)
    				for (int j=i+1;j<=n;j++)
    					for (int k=j+1;k<=n;k++)
    						for (int p=k+1;p<=n;p++)
    							for (int pp=p+1;pp<=n;pp++)
    							if (OK3(i,j,k,p,pp)) ans=(ans+1)%mo;
    		}
    		printf("Case #%d: %lld
    ", tt, ans%mo);
    	}
    	return 0;
    }
    
  • 相关阅读:
    【2021-01-26】保持学习,也是一种科学的健康保养方式
    【2021-01-25】正常市场化的企业该有的现象
    day 42 mysql 数据库(2)
    day 41 数据库初学习
    在排序数组中查找元素的第一个和最后一个位置
    飞机游戏
    两个数组的交集 II
    重复N次的元素
    单词规律
    存在重复元素2
  • 原文地址:https://www.cnblogs.com/71-111/p/13922046.html
Copyright © 2020-2023  润新知