• 小P的团战


    20191005 T2

    原题链接

    By GKurumi

    题目描述:

    升级过技能的小P已经具备开团能力,他现在有N个技能,准备单挑对面的M个人

    但小P血非常少,所以他必须要控制住对面所有M个人,不然就会死掉

    已知第i种技能可以控制住Ki个人,分别为(a_{i1},a_{i2}……,a_{ik})

    问有多少种放技能的方式控住对面所有(M)个人(控制技能只能放一次,只有顺序不同的方式被认为是同一种)

    答案对1000000007取模

    输入格式:

    第一行两个整数(N)(M)

    接下来N行,每行第一个整数表示Ki,接Ki个整数表示(a_{i1},a_{i2}……,a_{ik})

    输出格式:

    一个整数表示放技能的方式数目

    样例

    样例输入
    4 5
    2 2 3
    2 1 2
    4 1 2 3 5
    4 1 2 4 5
    

    样例输出

    6
    

    题解:

    ​ 首先,我是我们机房最菜的人

    ​ 这道题乍一看有点像组合计数,但是我不会 太麻烦了推不出来,于是我就回想起那个月黑风高的夜晚发生的事统计方案用状压,于是就走上了一条不归路。

    ​ 思路:我们用一个数组存下每个技能能打到的位置,之后开始状压dp,dp的时候在用另一个数组存此时用技能打第i位上敌人的方案数。跑一遍下来之后,再遍历查找一遍位置,当i位上有方案的时候就加上方案数,无方案的时候就减去(因为我一开始算了一遍总的方案数(鬼知道我怎么想的)(可能太想跟计数原理扯上关系)我爱计数原理!!也可以直接计算方案数,看个人的喜欢。
    转移方程:if(i&(1<<j))f[i^(1<<j)]+=f[i],w[i]++;
    计算方案数:(ans+=(w[i]&1?-1:1)*ksm(2,f[i]))%=mod;

    以防出锅最后ans如果成了负数,emmm,就这么mod:(ans+mod)%mod

    考试时卑微的代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define mod 1000000007
    int f[1<<20],w[1<<20];
    int read()
    {
    	int 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)+(ch-'0');ch=getchar();}
    	return x*f;
    }
    int ksm(int a,int b)
    {
    	int ans=1;
    	while(b)
    	{
    		if(b&1)ans=(ans*a)%mod;
    		b>>=1;
    		a=(a*a)%mod;
    	}
    	return ans;
    }
    int n,m,x,k,sum,ans;
    signed main()
    {
    	freopen("carry.in","r",stdin);
    	freopen("carry.out","w",stdout);
    	n=read();m=read();
    	sum=(1<<m)-1;
    	for(int i=1;i<=n;i++)
    	{
    		k=read();
    		int w=0;
    		for(int j=1;j<=k;j++)
    		{
    			x=read();
    			w|=(1<<(x-1));
    		}
    		f[w^sum]++;
    	}
    	ans=ksm(2,n);
    	for(int j=0;j<m;j++)
    	{
    		for(int i=(1<<m)-1;i!=0;i--)
    		{
    			if(i&(1<<j))f[i^(1<<j)]+=f[i],w[i]++;
    		}
    	}
    	for(int i=1;i<(1<<m);i++)
    	{
    		(ans+=(w[i]&1?-1:1)*ksm(2,f[i]))%=mod;
    	}
    	cout<<(ans+mod)%mod;
    	return 0;
    }
    

    本人第一次写博客,请多见谅。

    如有转载,请标明出处,谢谢。

  • 相关阅读:
    ThreadLocal内存泄漏真因探究(转)
    JAVA设计模式工厂模式
    java设计模式单例模式
    Java-Socket
    Java-Queue总结
    Java-Reentrantlock
    Java-Iterator遍历集合
    安装和启动docker
    C# System.Reflection.Assembly动态加载资源文件
    C#调用 kernel32.dll
  • 原文地址:https://www.cnblogs.com/GKurumi/p/11624879.html
Copyright © 2020-2023  润新知