专栏文章
题解:P13234 [GCJ 2015 Finals] Campinatorics
P13234题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioqx662
- 此快照首次捕获于
- 2025/12/02 23:41 3 个月前
- 此快照最后确认于
- 2025/12/02 23:41 3 个月前
小清新数数题,像是二维错排。
的限制是很好处理的,放置 个 相当于去除 行 列,问题规模缩小至 。
考虑只有 怎么做,设答案为 。
一个平凡的想法是从 转移而来。我们钦定第 行的第 个数为 ,然后枚举第 行 的位置 ,然后将原本第 列的 放置到第 列,这样我们就实现了一个 的映射,即
乘的 是把钦定的最后一行放回到任意一行中。
然而这样存在漏数的情况。类比错拍的递推,上式默认了去掉特定的一行一列(第 列有 的行,该行有 的列)后的矩阵依然合法,而则不总是存在。
考虑计算不存在的情况。容易发现,不存在当且仅当该特定的行列处于一个合法的 矩阵中(这也和错排类似),这一部分的贡献是 。
最后再处理 的影响即可。
时间复杂度 。
CPP#include<bits/stdc++.h>
#define il inline
using namespace std;
const int N=1000000;
const int maxn=1000010;
const int mod=1e9+7;
il int read(){
int x=0;
char c=getchar();
for(;!(c>='0'&&c<='9');c=getchar());
for(;c>='0'&&c<='9';c=getchar())
x=(x<<1)+(x<<3)+c-'0';
return x;
}
il int fpow(int n,int m,int x=1){
for(;m;m>>=1,n=1ll*n*n%mod)
if(m&1) x=1ll*x*n%mod;
return x;
}
int fac[maxn],ifac[maxn];
int f[maxn],T,n,X,ans;
int C(int i){return (1ll*i*(i-1)/2)%mod;}
int main(){
fac[0]=ifac[0]=1;
for(int i=1;i<=N;i++)
fac[i]=1ll*fac[i-1]*i%mod;
ifac[N]=fpow(fac[N],mod-2);
for(int i=N-1;i;i--)
ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
f[0]=1,f[1]=0,f[2]=2;
for(int i=3;i<=N;i++){
f[i]=1ll*f[i-1]*(i-1)%mod*i%mod;
f[i]=(f[i]+1ll*f[i-2]*i%mod*(i-1)%mod*(i-1))%mod;
}
// for(int i=1;i<=10;i++)
// printf("%d ",f[i]);
// printf("\n");
T=read();
for(int Case=1;Case<=T;Case++){
n=read(),X=read(),ans=0;
for(int i=1,tot=1;i<=n;i++){
tot=1ll*tot*(n-i+1)%mod*(n-i+1)%mod;
if(i>=X) ans=(ans+1ll*tot*f[n-i]%mod*ifac[i])%mod;
}
if(!X) ans=(ans+f[n])%mod;
printf("Case #%d: %d\n",Case,ans);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...