NOIP训练营试题及解析-死亡迷宫

网友投稿 2019-08-19 12:14

问题描述     众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关系。  现在有一个迷宫,这个迷宫是由若干个正 n=(4,6) 边形组成的 k层迷宫。如果 k = 1 ,那么该迷宫就由单独一个正 nn边形组成;如果 k>1,则在 k-1 层的基础上,沿着所有最外层的边增加一个正 n边形,新增加的正 n边形若有重叠,则保留其中一个即可。具体可以参考下图:‍‍ 描述及代码解析 ▋  现在为了打破迷宫的结界,你需要在迷宫的某些边上开一扇门。你总共要开 rr 扇门,每条边最多打开一扇门。但是如果两种开门的方案通过旋转相同,那么视为同一种方案。以及由于是死亡迷宫,所以死了也是可以的,所以你并不需要保证你开门的方案能够让你走出去。求总共的方案数。 【输入格式】   一行三个正整数 n,k,r 。 【输出格式】   一行一个整数代表答案对 10^9+7 取模之后的结果。 【样例输入】4 2 2 【样例输出】32 【数据规模与约定】   对于20%的数据, k = 1。   对于另外20%的数据, r = 1 。   对于另外20%的数据, k = 3。   对于50%的数据, n = 4。 ‍‍  对于100%的数据,  ‍ 代码: 1 #include #include #include #include #include using namespace std; int n,k,r; const int N=100010,M=100000,mod=1e9+7; inline int Plus(int a,int b){return a+b>=mod?a+b-mod:a+b;} inline int Del(int a,int b){return a< p=""> inline int Mul(int a,int b){return a*1ll*b%mod;} inline int qpow(int a,int b){int s=1;while(b){if(b&1)s=Mul(s,a);a=Mul(a,a);b>>=1;}return s;} int fac[N],inv[N]; inline void get_pre(){     fac[0]=1;for(int i=1;i<=M;++i)fac[i]=Mul(fac[i-1],i);     inv[M]=qpow(fac[M],mod-2);     for(int i=M-1;i>=0;--i)inv[i]=Mul(inv[i+1],i+1); }inline int C(int n,int m){     if(n<0)return 0;<="" p="">     return Mul(Mul(fac[n],inv[m]),inv[n-m]); } int main(){     scanf("%d%d%d",&n,&k,&r);     get_pre();     int ans=0;     if(n==4){         int p=4*k*k;         ans=Plus(ans,C(p,r));         if(!(r&1)){             ans=Plus(ans,C(p>>1,r>>1));             if(!((r>>1)&1))ans=Plus(ans,Mul(2,C(p>>2,r>>2)));         }     }else{         int p=3*(3*k-1)*k;         ans=Plus(ans,C(p,r));//循环节为1         if(r%2==0)ans=Plus(ans,C(p>>1,r>>1));         if(r%3==0)ans=Plus(ans,Mul(2,C(p/3,r/3)));         if(r%6==0)ans=Plus(ans,Mul(2,C(p/6,r/6)));     }     printf("%dn",Mul(ans,qpow(n,mod-2)));     return 0; } 题解:  

--end--

声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com