2339 [HNOI2011]卡农 (DP+去重)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88351496

题目在这里插入图片描述
我发现这神套路居然是黑题,原来大家都和我一样被套住了做不来啊。
首先最烦的是每一种都要有偶数个,然后发现并不烦,你前m-1个片段选好之后,最后一个也就是第m个片段就已经唯一确定了,然后这个限制就可以不用管了。。。。。。直接 d p [ i ] + = P 2 n 1 i 1 dp[i] += P_{2^n-1}^{i-1}
第二烦的就是不能有两个相同,然后就套路了,从前面 i 1 i-1 个元素中指定一个和当前的元素相同,然后减去,具体来说,就是 d p [ i ] = d p [ i 2 ] ( i 1 ) ( 2 n 1 ( i 2 ) ) dp[i]-=dp[i-2] * (i-1) * (2^n-1-(i-2))
最后就是去掉空集: d p [ i ] = d p [ i 1 ] dp[i]-=dp[i-1]
最后答案除上一个 m ! m! 就二次去重了。

AC Code:

#include<bits/stdc++.h>
#define mod 100000007
#define maxn 1000006
using namespace std;

int n,m,f[maxn];
int Pow(int base,int k)
{
	int ret=1;
	for(;k;k>>=1,base=1ll*base*base%mod)
		if(k&1)
			ret = 1ll*ret*base%mod;
	return ret;
}

int main()
{
	scanf("%d%d",&n,&m);
	n = Pow(2,n)-1;
	f[0] = 1 , f[1] = 0;
	int rfac=n , fac=m;
	for(int i=2;i<=m;i++) 
		f[i] = (1ll*rfac - f[i-1] - 1ll * f[i-2] * (i-1) % mod * (n-i+2)) % mod,
		rfac = 1ll * rfac * (n-i+1) % mod,
		fac = 1ll * fac * (m-i+1) % mod;
	printf("%lld\n",((1ll*f[m]*Pow(fac,mod-2)%mod)+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88351496