Codeforces 1227 F2 Wrong Answer on test 233 (Hard Version) —— 组合,想法

This way

题意:

给你1个长度为n的目标串,现在你自己有一个长度为n的串,你在每一个位置都可以放1-k中的某一个数,这样子放法就是 k n k^n 种。
假设当前你的串与目标串位置一一对应之后相同的地方有a个,把你的串向右循环移位一位之后你的串与目标串位置一一对应之后相同的地方有b个,问你有多少种情况a<b

题解:

首先,我的串第i位只与目标串的第i位与第i+1位有关系,此时可以分为4种状态:
00,01,10,11
0表示不相同,1表示相同。
那么,我们可以发现每个位置,如果是00的话,情况数有k-2种,01和10都是1种。
然后会发现,11这种情况是不需要考虑的,因为无论当a[i]=a[i+1]的时候,无论放什么数都不会有影响。所以我们设连续不相同的位置的数量为num。
之后找有多少情况是答案,我们会发现,假设01和10数量相等的情况是sum种,剩下的情况是 k n s u m k^n-sum 种,a比b多和b比a多的情况数是一样的,因为第i个位置是01的情况反一下就是10了,所以有 k n s u m 2 \frac{k^n-sum}{2} 种情况是答案。
所以枚举相同的情况数:
c ( n u m , i ) c ( n u m i , i ) q p o w ( k 2 , n u m 2 i ) q p o w ( k , n n u m ) c(num,i)*c(num-i,i)*qpow(k-2,num-2*i)*qpow(k,n-num)
k n k^n 减去这个数除2就是答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=998244353;
const int N=2e5+5;
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 fac[N],inv[N];
ll c(ll n,ll m){
    if(m>n||m<0)
        return 0;
    if(m==0||m==n)
        return 1;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int a[N];
int main()
{
    fac[0]=1;
    for(ll i=1;i<N;i++)
        fac[i]=fac[i-1]*i%mod,inv[i]=qpow(fac[i],mod-2);

    int n,num=0;
    ll k;
    scanf("%d%lld",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    a[0]=a[n];
    for(int i=1;i<=n;i++)
        num+=a[i]!=a[i-1];
    ll sum=0;
    for(ll i=0;i<=num/2;i++)
        sum=(sum+c(num,i)*c(num-i,i)%mod*qpow(k-2,num-2*i)%mod*qpow(k,n-num))%mod;
    sum=(qpow(k,n)-sum+mod)*qpow(2,mod-2)%mod;
    printf("%lld\n",sum);
    return 0;
}

发布了530 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104258518