放棋子
放棋子
-
看到题目后显然先想到 ,但是 ,那就肯定不行了。
-
题目理解:障碍与棋子一样,都是每行,列只有一个,因此,我们思考这样一个问题:
这两种情况的方案数有何区别?
-
答案是并无区别:显然第一种矩阵经过行与行(或列于列)的变换就能转化为第二种,而每一行每一列都会有一个障碍,因此,每一种矩阵都能转化为第二种,转化后每一行(或列)的方案数不变,总方案数当然也不变。
-
因此我们不考虑输入的矩阵,直接转化为第一种,认为障碍均在对角线上,于是,原问题就成了:在一个对角线不可放的棋盘放棋子,且每一列,每一行均只有一枚棋子。
-
进一步转化,问题就成了:一个数列 求方案数,这就是一个裸的错排问题了,例题:信封问题,没做过的同学可以自行了解一下,这里直接给出递推式:
-
考虑到 的增长速率极快,需要高精度辅助实现。
#include<bits/stdc++.h>
#define ll long long
const ll p=10000000000000000;
const int len=100010;
ll f[201][len],tem,pos;
void work(int n){
for(int i=1;i<=len;++i){
tem=f[n-1][i]+f[n-2][i];
f[n][i]=(tem+pos)%p;
pos=tem/p;
}
for(int i=1;i<=len;++i){
tem=f[n][i]*(n-1);
f[n][i]=(tem%p+pos);
pos=tem/p;
}
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
int a;scanf("%d",&a);
}没什么用的输入
if(n==1) return puts("0"),0;
if(n==2) return puts("1"),0;
f[1][1]=0;f[2][1]=1;
for(int i=3;i<=n;++i) work(i);
int len1(100010);
while(f[n][len1]==0&&len1>1) len1--;
printf("%lld",f[n][len1]);
while(--len1) printf("%016lld",f[n][len1]);
}
码风丑陋,见谅!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具