题目链接:https://ac.nowcoder.com/acm/contest/887/I
题意:首先给两个正整数n,m. 1<=n,m<=2000
然后构造K*K矩阵,要求k<=n,并且矩阵内每个元素都大于等于m,矩阵不同行不同列的元素加起来相等并且不超过n。
问有多少种构造方案。答案模99824435。
例 n=3,m=1有9种情况:
,,
,,,,
题解:
牛客给的题解:
关键是要理解 这一步
这个式子求出来是一个k*k的矩阵,并且满足了不同行不同列相加之和相等,并且相加之和等于a1+a2+...ak+b1+b2+...bk.
比如k=3
第一个矩阵是,第二个矩阵是,相加之后是
然后选3个不同行不同列的数,就能发现加起来都是 a1+a2+a3+b1+b2+b3.
这一步能理解了,最后为什么会多算也就能理解了
求a1+a2+...ak+b1+b2+...bk=t的方案数, ai>=0,bi>=0
那么方案数就是C(t+2k-1,2k-1) 高中学过,隔板法,百度一下就知道了
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=4005;
const int mod=998244353;
ll fac[maxn],ni[maxn];
ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
ll C(ll n,ll m){
if(n<0||m<0||n<m) return 0;
return fac[n]*ni[m]%mod*ni[n-m]%mod;
}
void init(){
fac[0]=1;
for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
ni[maxn-1]=ksm(fac[maxn-1],mod-2);
for(int i=maxn-2;i>=0;i--) ni[i]=ni[i+1]*(i+1)%mod;
}
int main(){
init();
int t;
scanf("%d",&t);
while(t--){
ll n,m;
scanf("%lld%lld",&n,&m);
ll ans=0;
for(ll i=1;i<=n;i++){
for(ll j=m*i;j<=n;j++){
int x=j-m*i;
ans=(ans+C(x+2*i-1,2*i-1)-C(x+i-1,2*i-1)+mod)%mod;
}
}
printf("%lld\n",ans);
}
return 0;
}