Codechef:Billboards/BB(楊氏矩陣)
阿新 • • 發佈:2018-11-01
題解:
顯然的一點就是如果
那麼相當與是每隔
個塊裡面就要放
個,而且每個塊這
箇中每一個的位置都單調不降。
此時相當於就是統計一下半標準楊氏矩陣(列單調降,行非嚴格單調降)的個數,根據鉤子定理,可以知道,當矩陣中最大元素為
時,楊氏矩陣方案數為:
為 位置的鉤子長度。
然後會發現乘法和除法有很多位置是相同的,去掉這些相同的之後,就變成了只需要求 列的乘積,這個直接暴力是 的,用一點技巧就可以優化到 。
稍微討論一下就可以轉化為 的情況了。
#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();
}