Bzoj2339--Hnoi2011卡农
Posted ihopenot
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj2339--Hnoi2011卡农相关的知识,希望对你有一定的参考价值。
题意 :
给你n个音阶,要求组成一个长m个片段的音乐有多少方案。
每个片段里每种音阶至多含有一个,任意两个片段包含的音阶不能完全相同,并且每一种音乐里每个音阶出现的次数必须是偶数次。
两个音乐不同的话当且仅当不存在任意一种对应方案使a包含的片段与b包含的片段完全相同。
eg. {{1,2},{2,3}}与{{2,3},{1,2}}是相同的音乐。(虽然都不是合法的音乐
数据范围 :
n,m <= 1000000
----------------------------------------------------------------此后一千里----------------------------------------------------------
我们考虑如果选定了m - 1个片段,那么最后一个片段显然已经确定了,因为每种音阶必须出现偶数次
所以我们从所有2^n - 1中片段中选出m - 1个的方案就是C(2^n - 1,m - 1)
那么算多了的方案就是选出了m - 1个片段已经是合法音乐,那么我们加入的最后一个片段就会是空集,这个要减掉
还有最有一个片段如果与之前的片段有重复,那么去掉这两个相同的片段,剩下的一定是个合法音乐,这两个片段就有 2^n - 1 - (m - 2)中选择方案
然后递推式 : f[i] = (C(2^n - 1,m - 1) - f[i - 1] - f[i - 2] * (2^n - m + 1) )/ i
除 i 是因为每一种合法方案被计算了 i 次
ps : 自己想的时候一直在想怎么容斥掉有相同的情况,发现没法容斥,没想到直接去搞组合数就可以了。。。。
代码 :
/* Lelouch vi Britannia here commands you , all of you , die ! */ #include<bits/stdc++.h> #define INF 0x3f3f3f3f #define low(x) ((x)&(-(x))) #define LL long long #define eps 1e-9 #define MOD 100000007 using namespace std; #define int int inline int Max(int a,int b) {return a>b?a:b;} inline int Min(int a,int b) {return a<b?a:b;} inline int Abs(int a) {return a>0?a:-a;} inline int Sqr(int a) {return a*a;} #undef int #define MAXN 1000006 int n,m; LL two[MAXN],C[MAXN],f[MAXN],ni[MAXN]; void Pre() { two[0]=1;C[0]=1;ni[1]=1; for(int i=1;i<=n;i++) two[i]=two[i-1]*2%MOD; for(int i=2;i<=m;i++) ni[i]=(MOD-MOD/i)*ni[MOD%i]%MOD; for(int i=1;i<=m;i++) C[i]=C[i-1]*(MOD+two[n]-i)%MOD*ni[i]%MOD; } int main() { scanf("%d%d",&n,&m); Pre(); if(C[m-1]<2||!m) f[m]=0; else { f[0]=1; for(int i=2;i<=m;i++) { f[i]=((C[i-1]-f[i-1]-f[i-2]*(MOD+two[n]-i+1)%MOD)%MOD+MOD)%MOD; f[i]=f[i]*ni[i]%MOD; } } printf("%lld\n",f[m]); return 0; } /* Hmhmhmhm . That‘s right , I am killer. */
以上是关于Bzoj2339--Hnoi2011卡农的主要内容,如果未能解决你的问题,请参考以下文章