【题解】arc189_a Reversi 2

arc189_a Reversi 2

简要题意

给定一个序列 \(b\),初始时 \(b_i=i\bmod 2\)

输入一个序列 \(a\)\(a_i\in \{0,1\}\)

可以进行任意次如下操作:

  • 选定 \(l,r(r-l>1)\),对每一个 \(i\in [l+1,r-1]\),执行 \(a_i\leftarrow a_l\)

当然,执行是有条件的,得满足 \(a_l=a_r\),且 \(\forall i\in [l+1,r-1],a_i\neq a_l\)

问有多少种不同的操作序列能使得 \(b\) 变换为 \(a\)

题解

知识点:排列组合。

启发:

  • 多重集排列数

典型的 ARC style 题目,小巧精妙,适合静下心仔细推敲。

看着没什么思路,不妨找点性质。

选定的 \(l,r\),要求 \(a_l=a_r\),操作前还需要满足 \(\forall i\in [l+1,r-1],a_i\neq a_l\),操作是将 \(a_{l+1}\sim a_{r-1}\) 赋值为 \(a_l\),所以这个操作可以看作给 \(a_{l+1}\sim a_{r-1}\) 取反。

当一个 \(i\) 被之前的操作成功取反后,\(i\) 在之后将无法作为一个 \(l\) 或者 \(r\) 参与操作,因为肯定有 \(a_{i-1}=a_i=a_{i+1}\)

当一个 \(i\) 作为 \(l\) 后,将不可能再作为 \(l\)

同理,当一个 \(i\) 作为 \(r\) 后,也不可能再作为 \(r\)

考虑对 \(a\) 每一个颜色段(连续的 0 或者 1)求解,相邻颜色段间是独立的,原因是操作的 \(l,r\) 应该满足 \(a_l=a_r\)

每一个段的长度一定是奇数,不然无解,因为此时 \(b\) 的左端点和右端点不同,无法操作成同色。

长度为 \(1\) 的段对答案无贡献,无法进行操作,不过不能忽略,因为要判无解。

考虑什么时候无解,对于段 \([l,r]\),以下情况会导致无解:

  • \(a_l\neq a_r\)

  • \(a_l\neq l\bmod 2\)

  • \(a_r\neq r\bmod 2\)

可以发现上面的条件已经顺便把 \(r-l+1\) 为奇数判了。

现在考虑每个颜色段的贡献计算,目的是将 01 交替的段转化为全为 0 或者 1 的段,由于两种情况通过置换后完全等价,只考虑将 1 开头并 01 交替的段转化为全为 1 的段。

设一个 01 交替段长度为 \(len\)

初始时共有 \(len-2\)\((l,r)\) 可进行操作,每次操作后,对数都会减少 \(2\),直到减少到 \(1\),此时再操作,便成为了全 1 的段,故不管怎么操作,操作次数都为 \(\lfloor \frac{len-2}{2} \rfloor +1=\frac{len-1}{2}\) 次。

准备进行第 \(i\) 次操作时,有 \(len-2-2(i-1)=len-2i\) 对可选的 \((l,r)\) 操作,故操作方案数为 \(\displaystyle \prod_{i=1}^\frac{len-1}{2} (len-2i)=\prod_{i=1}^{\frac{len-1}{2}} (2i-1)\)

接下来考虑段之间贡献的合并。

除了简单地将各自的操作方案数相乘,还得考虑到操作可以交替进行,段之间的操作存在顺序,段内的顺序已经被前面考虑,所以要用到多重集的排列数,设有 \(k\) 个段,第 \(i\) 个段有 \(s_i\) 次操作,设 \(\displaystyle N=\sum_{i=1}^k{s_i}\),则排列数为:

\[\displaystyle \frac{N!}{\prod_{i=1}^k s_i!} \]

设段长为 \(l_i\),那么总的答案就是:

\[\large \displaystyle \frac{(\sum_{i=1}^k \frac{l_i-1}{2})!}{\prod_{i=1}^k (\frac{l_i-1}{2})!} \times \prod_{j=1}^k \prod_{i=1}^{\frac{l_j-1}{2}} (2i-1) \]

#include<bits/stdc++.h>
using namespace std;

#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()

#define N 202507
#define int long long

const int mod=998244353;
int n,a[N],fac[N],cnt[N];

inline int inv(int a){
    int b=mod-2,ans=1;

    while(b){
        if(b&1){
            ans=ans*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }

    return ans;
}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    cin>>n;

    fac[0]=1;

    rep(i,1,n){
        cin>>a[i];
        fac[i]=fac[i-1]*i%mod;
    }

    {
        cnt[3]=1;
        int st=5;

        while(st<=n){
            cnt[st]=cnt[st-2]*(st-2)%mod;
            st+=2;
        }
    }

    vector<pr>v;

    int sum=0;

    int ls=1;
    rep(i,1,n){
        if(a[i]!=a[ls]){
            int l=ls,r=i-1;
            sum+=(r-l)/2;

            v.pb({ls,i-1});
            ls=i;
        }
    }

    v.pb({ls,n});
    sum+=(n-ls)/2;

    int ans=fac[sum];

    for(pr u:v){
        int l=u.fi,r=u.se;

        if(a[l]!=a[r]||a[l]!=l%2||a[r]!=r%2){
            cout<<0;
            return 0;
        }

        if(l==r){
            continue;
        }

        ans=ans*inv(fac[(r-l)/2])%mod;
        ans=ans*cnt[r-l+1]%mod;
    }

    cout<<ans;

    return 0;
}
posted @ 2025-07-08 22:13  Lucyna_Kushinada  阅读(23)  评论(0)    收藏  举报