专栏文章

题解:CF2150B Grid Counting

CF2150B题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mingl907
此快照首次捕获于
2025/12/02 02:04
3 个月前
此快照最后确认于
2025/12/02 02:04
3 个月前
查看原文

题解:CF2150B Grid Counting

思路

首先,因为题目的第二、三条限制,每个 kk 都对应一个黑色格子,所以黑色格子一共有 nn 个。
首先,我们必须在 (1,1)(1,1)(1,n)(1,n) 位置放黑色格子,因为只有他们能满足 k=1k=1 时的第二、三条限制。
那么,在 (1,1)(1,1) 下面的格子就必须都为白色,因为 (1,1)(1,1) 对于第三条限制的 k=nk=n,此时 (1,1)(1,1)nyi+1n-y_i+1 为最大值,而在 (1,1)(1,1) 下面的点的的 yi=1y_i=1,和 (1,1)(1,1) 相等,所以不能选,以此类推,在 (1,n)(1,n) 下面的格子也必须为白色。
接下来考虑第二、三条限制 k=2k=2 的情况,因为第 11nn 列不能选,所以只能选第 22n1n-1 列中 xi2x_i \ge 2 的格子。
以此类推,最终能选的格子即为下图:
其中黑色为必选的部分,灰色为可选的部分(每列选一个)。
那么接下来我们倒序枚举 nn11,设当前一共可以放的黑色格子数量为 cntcnt,每遇到可以放黑色格子的行就将 cntcnt 加上本行加的黑色格子数量,比如到第 22 行可以多放两个,如果 cnt<aicnt<a_i 则无解,每次将答案乘上 (cntai)\dbinom{cnt}{a_i} 即可。

代码

CPP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
int t,n,a[200010];
ll f[200010];
ll qpow(ll a,ll b){
    ll ans=1;
    for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
    return ans;
}
ll C(ll n,ll m){
    if(n<m)return 0;
    return f[n]*qpow(f[m],mod-2)%mod*qpow(f[n-m],mod-2)%mod;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    f[0]=1;
    for(int i=1;i<=200000;i++)f[i]=f[i-1]*i%mod;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        int cnt=0,fl=1;
        ll ans=1;
        for(int i=n;i>=1;i--){
            if(i*2==n+1)cnt++;
            else if(i*2<=n)cnt+=2;
            if(cnt<a[i]){
                fl=0;
                break;
            }
            ans=ans*C(cnt,a[i])%mod;
            cnt-=a[i];
        }
        if(cnt!=0||!fl){
            cout<<"0\n";
        }
        else{
            cout<<ans<<'\n';
        }
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...