zoukankan      html  css  js  c++  java
  • [atAGC051D]C4

    考虑将两次移动作为一个整体,两次移动的效果分为:$s-u$、$u-s$和原地不动

    对于从$s$回到$s$路径,必然有前两种效果使用次数相同,假设都为$i$(枚举),那么原地不动的次数$j=frac{a+b+c+d}{2}-i$

    $2i$次中使用$t$来移动的次数$x$,那么使用$v$的次数即为$y=2i-x$,之后这里有$2ichoose x$种方案(注意这$2i$次操作顺序已经确定,必然是$s-u$再$u-s$循环排列)

    考虑原地不动的贡献:在$s$上原地不动的$frac{a+d}{2}-i$次(这里分子要减去$x+y$,即$2i$)划分为了$i+1$段(可以为空,通过插板法计算),且内部有$frac{a+d}{2}-ichoose frac{a-x}{2}$种排列,在$t$上原地不动的类似

    综合上述,即$[b+c=0]{a+dchoose a}+sum_{i=1}^{frac{a+b+c+d}{2}}sum_{x=0}^{2i}{2ichoose x}{frac{a+d}{2}choose i}{frac{a+d}{2}-ichoose frac{a-x}{2}}{frac{b+c}{2}-1choose i-1}{frac{b+c}{2}-ichoose frac{b-x}{2}}$

    对后半部分化简,即$(frac{a+d}{2})!(frac{b+c}{2}-1)!sum_{i=0}^{frac{a+b+c+d}{2}}frac{(2i)!}{i!(i-1)!}sum_{x=0}^{2i}frac{1}{x!(frac{a-x}{2})!(frac{b-x}{2})!(2i-x)!(frac{d-(2i-x)}{2})!(frac{c-(2i-x)}{2}))}$

    关于$x$的枚举是一个多项式乘法的形式,即记$h(x)=frac{1}{x!(frac{a-x}{2})!(frac{b-x}{2})!}$且$g(x)=frac{1}{x!(frac{d-x}{2})!(frac{c-x}{2})!}$,考虑$f(x)=g(x)h(x)$的$k$次项系数即为$i=frac{k}{2}$时后面的值,用ntt计算即可,时间复杂度为$o(nlog_{2}n)$(其中$n=a+b+c+d$)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 5000005
     4 #define mod 998244353
     5 int n,a,b,c,d,ans,fac[N],inv[N],rev[N],g[N],f[N];
     6 int C(int n,int m){
     7     return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
     8 }
     9 int ksm(int n,int m){
    10     if (!m)return 1;
    11     int s=ksm(n,m>>1);
    12     s=1LL*s*s%mod;
    13     if (m&1)s=1LL*s*n%mod;
    14     return s;
    15 }
    16 void ntt(int *a,int p){
    17     for(int i=0;i<(1<<22);i++)
    18         if (i<rev[i])swap(a[i],a[rev[i]]);
    19     for(int i=2;i<=(1<<22);i*=2){
    20         int s=ksm(3,(mod-1)/i);
    21         if (p)s=ksm(s,mod-2);
    22         for(int j=0;j<(1<<22);j+=i)
    23             for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){
    24                 int x=a[j+k],y=1LL*a[j+k+(i>>1)]*ss%mod;
    25                 a[j+k]=(x+y)%mod;
    26                 a[j+k+(i>>1)]=(x+mod-y)%mod;
    27             }
    28     }
    29     if (p){
    30         int s=ksm((1<<22),mod-2);
    31         for(int i=0;i<(1<<22);i++)a[i]=1LL*a[i]*s%mod;
    32     }
    33 }
    34 int main(){
    35     fac[0]=inv[0]=inv[1]=1;
    36     for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod;
    37     for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
    38     for(int i=1;i<N-4;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod;
    39     scanf("%d%d%d%d",&a,&b,&c,&d);
    40     if (((a+d)&1)||((b+c)&1)||((a+b)&1)){
    41         printf("0");
    42         return 0;
    43     }
    44     if ((!b)&&(!c)){
    45         printf("%d",C(a+d,a));
    46         return 0;
    47     }
    48     n=a+b+c+d;
    49     for(int i=0;i<(1<<22);i++)rev[i]=(rev[i>>1]>>1)+((i&1)<<21);
    50     for(int i=0;i<=min(a,b);i++)
    51         if ((a-i)%2==0)f[i]=1LL*inv[i]*inv[(a-i)/2]%mod*inv[(b-i)/2]%mod;
    52     for(int i=0;i<=min(c,d);i++)
    53         if ((c-i)%2==0)g[i]=1LL*inv[i]*inv[(c-i)/2]%mod*inv[(d-i)/2]%mod;
    54     ntt(g,0);
    55     ntt(f,0);
    56     for(int i=0;i<(1<<22);i++)f[i]=1LL*f[i]*g[i]%mod;
    57     ntt(f,1);
    58     for(int i=1;i<=(b+c)/2;i++)ans=(ans+1LL*fac[2*i]*inv[i]%mod*inv[i-1]%mod*f[2*i])%mod;
    59     ans=1LL*ans*fac[(a+d)/2]%mod*fac[(b+c)/2-1]%mod;
    60     printf("%d",ans);
    61 } 
    View Code
  • 相关阅读:
    HTML+CSS知识点总结
    消灭textarea中的神秘空格
    OAuth2.0
    C# task和timer实现定时操作
    C# 多线程task
    EF的使用
    支付宝支付开发
    Basic Auth
    C#中匿名函数、委托delegate和Action、Func、Expression、还有Lambda的关系和区别
    [转]CodeSite使用小结
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14237598.html
Copyright © 2011-2022 走看看