AFO

2339: [HNOI2011]卡农

Description

img


首先去除顺序不同算一种的麻烦,就是最后答案除以总片段数\(2^m-1\)

\(f_i\)表示安排\(i\)个片段的合法种类

那么对于任何一个包含\(i-1\)个片段的序列(除了发\(f_{i-1}\)的那几个合法序列)都能再找到唯一一个片段使得整个序列变为合法序列(那种和旋是基数个就选上)。但是还有一种特例就是可能这个新选的片段已经在序列里了,这种情况下把这两个相同的片段去掉肯定还是合法序列啊,就是\(f_{i-2}\)

所以总柿子就是$$f_i= A_{2m-1}-f_{i-1}-f_{i-2}(i-1)(2^m+1-i)$$


#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define M 100000007
using namespace std;

LL m,n,j,k,a[1000001],f[1000001],t=1,g=1,d=1;

LL pow(LL x,LL y) 
{
	LL z=1;
	for(y;y>1;y>>=1,x=x*x%M) if(y&1) z=z*x%M;
	return x*z%M;
}

int main()
{
	a[0]=f[0]=1;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++) t=t*2%M;  t=(t-1+M)%M;
	for(int i=1;i<=m;i++) a[i]=a[i-1]*((t-i+1+M)%M)%M,d=d*i%M;
	for(int i=2;i<=m;i++) f[i]=((a[i-1]-f[i-1]+M-f[i-2]*(i-1)%M*(t-i+2+M)%M)%M+M)%M;
	printf("%lld",f[m]*pow(d,M-2)%M);
}
posted @ 2019-09-01 22:03  ZUTTER☮  阅读(148)  评论(0编辑  收藏  举报