版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/83340204
题解:
显然的一点就是如果
那么相当与是每隔
个块里面就要放
个,而且每个块这
个中每一个的位置都单调不降。
此时相当于就是统计一下半标准杨氏矩阵(列单调降,行非严格单调降)的个数,根据钩子定理,可以知道,当矩阵中最大元素为
时,杨氏矩阵方案数为:
为 位置的钩子长度。
然后会发现乘法和除法有很多位置是相同的,去掉这些相同的之后,就变成了只需要求 列的乘积,这个直接暴力是 的,用一点技巧就可以优化到 。
稍微讨论一下就可以转化为 的情况了。
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (long long)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
inline int cinv(int x) {return power(x,mod-2);}
inline int calc(int i,int k) {
int ans=1;
for(int j=0;j<k;j++) ans=mul(ans,i-j);
return ans;
}
inline int calc(int l1,int r1,int l2,int r2,int k) {
int ans=1;
if(l1>r2) {
for(int i=l1;i<=r1;i++) ans=mul(ans,calc(i,k));
for(int i=l2;i<=r2;i++) ans=mul(ans,cinv(calc(i,k)));
} else {
for(int i=r2+1;i<=r1;i++) ans=mul(ans,calc(i,k));
for(int i=l2;i<=l1-1;i++) ans=mul(ans,cinv(calc(i,k)));
} return ans;
}
inline void solve() {
int n,m,k;
cin>>n>>m>>k;
if(!(n%m)) n/=m;
else {
int res=n%m; n=n/m+1;
if(m-res<=k) {
k=k-(m-res);
m=res;
} else {
m=m-res; --n;
}
}
cout<<calc(m,m+n-1,k,k+n-1,k)<<'\n';
}
int main() {
int T; cin>>T;
while(T--) solve();
}