2019牛客暑期多校训练营(第七场)I题Chessboard 组合数学

题目链接: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种情况:

\begin{bmatrix} 1 \end{bmatrix}\begin{bmatrix} 2\end{bmatrix}\begin{bmatrix} 3 \end{bmatrix}

\begin{bmatrix} 1 &1 \\ 1 & 1 \end{bmatrix}\begin{bmatrix} 2 &2 \\ 1 & 1 \end{bmatrix}\begin{bmatrix} 2 &1 \\ 2 & 1 \end{bmatrix}\begin{bmatrix} 1 &1 \\ 2 & 2 \end{bmatrix}\begin{bmatrix} 1 &2 \\ 1 &2 \end{bmatrix}

\begin{bmatrix} 1 &1 &1 \\ 1& 1 & 1\\ 1 & 1& 1 \end{bmatrix}

题解:

牛客给的题解:

关键是要理解 \sum_{i=1}^{k}aiAi+\sum_{i=1}^{k}biBi这一步

这个式子求出来是一个k*k的矩阵,并且满足了不同行不同列相加之和相等,并且相加之和等于a1+a2+...ak+b1+b2+...bk.

比如k=3

第一个矩阵是\begin{bmatrix} a1 & a1 &a1 \\ a2&a2 &a2 \\ a3&a3 &a3 \end{bmatrix},第二个矩阵是\begin{bmatrix} b1 & b1 &b1 \\ b2&b2 &b2 \\ b3&b3 &b3 \end{bmatrix},相加之后是\begin{bmatrix} a1+b1 & a1+b2 &a1+b3 \\ a2+b1&a2+b2 &a2+b3 \\ a3+b1&a3+b2 &a3+b3 \end{bmatrix}

然后选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;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值