zoukankan      html  css  js  c++  java
  • 【atcoder】GP 2 [agc036C]

      题目传送门:https://atcoder.jp/contests/agc036/tasks/agc036_c

      题目大意:给你一个长度为$N$初始全0的序列,每次操作你可以找两个不同的元素,一个自增1,一个自增2,问$M$次操作后,能出现多少种不同的序列。

      这道题比赛时分析的时候漏条件了,导致最后一个样例一直过不去,不过考虑上漏掉的条件分析起来也是比较复杂的。

      我们可以发现如果一个序列$a$是合法的,当且仅当它满足以下条件:

        1. $sum_{i=1}^{N} a_i=3M$。

        2. 整个序列里至多有$M$个奇数。

        3. $max_{i=1}^{N} a_i<=2M$。

      证明可以考虑对$M$数学归纳。

      我们可以先忽略条件3,枚举奇数的个数$i$,那么就是相当于对于一个全是偶数的数列,选择$i$个加上1,总方案数为$sum_{i=1}^{min(N,M)}inom{N}{i}inom{N-1+3M-i}{N-1}$,可以在$O(n+m)$的时间复杂度下计算。

      然后在考虑减去不满足条件3的方案数。由于序列中大于$2M$的元素最多只有一个,因此我们可以钦定那个大于$2M$的元素为$a_1$,并将其减去$2M$,这样操作后的序列,并且原序列如果满足原序列是满足条件1,2,不满足条件3,当且仅当操作后的序列满足以下条件:

        a. $sum_{i=1}^{N} a_i=3M$。

        b. 整个序列至多有$M$个奇数。(减去$2M$不改变奇偶性)

        c. $a_1>0$。

      我们再把这些方案看作两部分相减:忽略条件c的方案减去考虑条件c非法的答案,而我们发现这样的忽略条件c的方案条件与上面的条件1,2相似,可以用相似方法统计,而考虑条件c时因为钦定$a_1=0$,所以直接序列整体平移,$N$自减1再统计即可。

      代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    #define mod 998244353
    #define Mod1(x) (x>=mod?x-mod:x)
    #define Mod2(x) (x<0?x+mod:x)
    #define maxn 3000010
    inline ll read()
    {
        ll x=0; char c=getchar(),f=1;
        for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1;
        for(;'0'<=c&&c<='9';c=getchar())x=x*10+c-'0';
        return x*f;
    }
    inline void write(ll x)
    {
        static int buf[20],len; len=0;
        if(x<0)x=-x,putchar('-');
        for(;x;x/=10)buf[len++]=x%10;
        if(!len)putchar('0');
        else while(len)putchar(buf[--len]+'0');
    }
    inline void writeln(ll x){write(x); putchar('
    ');}
    inline void writesp(ll x){write(x); putchar(' ');}
    ll fac[maxn],inv[maxn];
    int n,m;
    inline ll power(ll a,ll b)
    {
        ll ans=1;
        for(;b;b>>=1,a=a*a%mod)
            if(b&1)ans=ans*a%mod;
        return ans;
    }
    inline ll C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
    inline ll calc(int n,int m,int k)
    {
        ll sum=0;
        for(int i=0;i<=n&&i<=k;i++)
            if(!((m-i)&1)&&m>=i)sum=(sum+C(n,i)*C((m-i)/2+n-1,n-1))%mod;
        // writeln(sum);
        return sum;
    }
    int main()
    {
        n=read(); m=read();
        fac[0]=inv[0]=1;
        for(int i=1;i<=n+3*m;i++){
            fac[i]=fac[i-1]*i%mod;
            inv[i]=power(fac[i],mod-2);
        }
        ll ans=(calc(n,3*m,m)-n*(calc(n,m,m)-calc(n-1,m,m)+mod))%mod;
        writeln(Mod2(ans));
        return 0;
    }
    agc036C
  • 相关阅读:
    🔥低代码音视频开发训练营火热报名中!
    编解码再进化:Ali266 与下一代视频技术
    ICCV 2021口罩人物身份鉴别全球挑战赛冠军方案分享
    提升 RTC 音频体验 从搞懂硬件开始
    只要你有目标,只要你肯努力,成功只是时间问题
    安全感到底来自何方
    工作经验小结
    女人的出路在何方?
    那些以为过去了的
    初出茅庐
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/11228893.html
Copyright © 2011-2022 走看看