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

问题描述
众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关系。
 现在有一个迷宫,这个迷宫是由若干个正 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<b?a-b+mod:a-b;}
inline int Mul(int a,int b){return a1llb%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<m||m<0)return 0;
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(n4){
int p=4kk;
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%30)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("%d\n",Mul(ans,qpow(n,mod-2)));
return 0;
}

题解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关注「信息学竞赛」
看更多信息学趣闻与知识
↓↓↓

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值