您的位置:首页 > 其它

bzoj2339 [HNOI2011]卡农

2017-09-15 14:31 204 查看

Description



正解:数学。

这种数学题自己根本就想不到啊。。

首先我们可以把片段看成有序的,只要最后除一下$m!$就行了。

然后我们考虑$m$个片段的所有情况(包括不合法的)为$A_{2^{n}-1}^{m-1}$。

当前$m-1$个片段确定以后,第$m$个片段肯定也能确定了。

上面考虑到了每个数必须出现偶数次,但是没有考虑第$m$个片段是空集和与前$m-1$个片段重复的情况。

那么我们设$f[m]$表示$m$个片段的合法情况,考虑怎么去掉空集和重复的情况。

当第$m$个片段是空集时,显然,这是因为前$m-1$个片段已经是合法情况,所以才有这种情况,那么减去$f[m-1]$就行了。

当第$m$个片段与前面某一片段重复时,我们可以枚举这是第几个片段,总共有$m-1$个这样的片段。

于是拿掉这两个片段以后,剩下的$m-2$个片段又是合法情况了,再考虑这两个片段的方案数,可以得到我们需要减去的就是$(m-1)*f[m-2]*[2^{n}-1-(i-2)]$。

于是这道题我们就做完了。

#include <bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define rhl (100000007)
#define N (1000010)

using namespace std;

ll f
,g
,bin,fac,n,m;

il ll qpow(RG ll a,RG ll b){
RG ll ans=1;
while (b){
if (b&1) ans=ans*a%rhl;
a=a*a%rhl,b>>=1;
}
return ans;
}

int main(){
#ifndef ONLINE_JUDGE
freopen("canon.in","r",stdin);
freopen("canon.out","w",stdout);
#endif
cin>>n>>m,bin=(qpow(2,n)-1+rhl)%rhl,g[0]=fac=1;
for (RG ll i=1;i<=m;++i) g[i]=g[i-1]*(bin-i+1+rhl)%rhl,fac=fac*i%rhl;
for (RG ll i=3;i<=m;++i)
f[i]=(g[i-1]-f[i-1]+rhl-(i-1+rhl)*f[i-2]%rhl*(bin-i+2+rhl)%rhl+rhl)%rhl;
cout<<f[m]*qpow(fac,rhl-2)%rhl; return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: