首先,决斗的过程可以看成一颗满二叉树。进入决赛表示根节点的左或右子树中最大的那个。我们记m=2^(k-1) 表示所有骑士的一半。
那么,1-m-1都没有机会赢。对于第i个骑士,自己的位置有2*m个,然后比自己弱的i-1个中选m-1个放在自己同一侧。最后对m-1个和m个进行全排序。
最后的结果就是:2m*C(i-1,m-1)*m!*(m-1)! =2*m!*m!*C(i-1,m-1)
对于C(i-1,m-1),由于一定选m-1个,所以有递推 C(i,m-1)=C(i-1,m-1)*i/(i+1-m)。
按照思路写好后一直wa。 在队友的帮助下,学习了逆元的知识:
要算a/b%m 可以找到b的逆元bb,逆元就是b*bb%m=1,那么a/b%m就是a*bb%m
一般m 为质数(10^9+7之类的) 的时候 bb的取值可以是b^(m-2)
递推修改成 C(i,m-1)=C(i-1,m-1)*i * Power(i+1-m,mod-2) 即可。 * 和 % 应该是按顺序算的。
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX=1<<20,mod=1e9+9;
typedef long long LL;
LL bit[20],fac[MAX];
void init(){
bit[0]=1,fac[0]=1;
for(int i=1;i<20;i++)
bit[i]=bit[i-1]*2;
for(int i=1;i<MAX;i++)
fac[i]=(fac[i-1]*i)%mod;
}
LL Power(LL x,int cf){
LL rst=1;
while(cf){
if(cf%2)
rst=(rst*x)%mod;
x=(x*x)%mod;
cf>>=1;
}
return rst;
}
int main(){
int k;
init();
while(cin>>k){
LL p=bit[k-1],mx=bit[k];
LL A=fac[p]*fac[p]%mod*2%mod;
LL C=1,ans;
for(int i=1;i<=mx;i++){
if(i>=p){
ans=(A*C)%mod;
C=C*i%mod*Power(i+1-p,mod-2)%mod;// 除k = 乘k的逆元(k^(mod-2))
printf("%lld\n",ans);
}
else
printf("0\n");
}
}
return 0;
}