P3214 [HNOI2011] 卡农
P3214 [HNOI2011] 卡农
考虑将前面 \(m-1\) 个集合放好后,最后一个集合由于需要满足所有元素出现次数为偶数,只有一种填法。对于一些特殊的前面 \(m-1\) 个集合,最后一个集合无解。
考虑哪些前面的集合会使得最后一个集合不合法。
- 前面 \(m-1\) 个集合恰好使得每个元素出现次数均为偶数。
- 当前元素出现次数为奇数的集合在前面 \(m-1\) 个集合中已经出现,此时将这个集合去掉后一定使得每个元素的出现次数为偶数。
去掉重新排列后相同的限制,最后除以 \(m!\) 即可。
考虑设 \(f_i\) 表示放置 \(i\) 个集合的答案。则有
\[f_i=\binom{(2^n-1)}{i-1}\times (i-1)!-f_{i-1}-(i-1)(2^n-1-(i-2))\times f_{i-2}
\]
其中 \(f_0=1,f_1=0\)。
化简式子,得到
\[f_i=\frac{(2^n-1)!}{(2^n-i)!}-f_{i-1}-(i-1)(2^n-1-(i-2))\times f_{i-2}
\]
时间复杂度 \(\mathcal{O}(m+\log p)\)。
code
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>inline bool read(T &x){
x=0;
char ch=getchar();
bool flag=0,ret=0;
while(ch<'0'||ch>'9') flag=flag||(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(),ret=1;
x=flag?-x:x;
return ret;
}
template<typename T,typename ...Args>inline bool read(T& a,Args& ...args){
return read(a)&&read(args...);
}
template<typename T>void prt(T x){
if(x>9) prt(x/10);
putchar(x%10+'0');
}
template<typename T>inline void put(T x){
if(x<0) putchar('-'),x=-x;
prt(x);
}
template<typename T>inline void put(char ch,T x){
if(x<0) putchar('-'),x=-x;
prt(x);
putchar(ch);
}
template<typename T,typename ...Args>inline void put(T a,Args ...args){
put(a);
put(args...);
}
template<typename T,typename ...Args>inline void put(const char ch,T a,Args ...args){
put(ch,a);
put(ch,args...);
}
inline void put(string s){
for(int i=0,sz=s.length();i<sz;i++) putchar(s[i]);
}
inline void put(const char* s){
for(int i=0,sz=strlen(s);i<sz;i++) putchar(s[i]);
}
}
using namespace IO;
#define mod 100000007
int f[1000005],n,m,siz,prod,ifac=1;
inline int add(int x,int y){
return (x+y)>=mod?x+y-mod:x+y;
}
inline int mul(int x,int y){
return (long long)x*y%mod;
}
inline int power(int x,int y){
int res=1;
while(y){
if(y&1) res=mul(res,x);
x=mul(x,x);
y>>=1;
}
return res;
}
int main(){
read(n,m);
siz=add(power(2,n),mod-1);
for(int i=1;i<=m;i++) ifac=mul(ifac,i);
f[0]=1,f[1]=0,prod=1;
for(int i=2;i<=m;i++){
prod=mul(prod,siz-i+2);
int tmp=add(f[i-1],mul(mul(i-1,siz-i+2),f[i-2]));
f[i]=add(prod,mod-tmp);
}
put('\n',mul(f[m],power(ifac,mod-2)));
return 0;
}

浙公网安备 33010602011771号