CTS2019珍珠

Posted weiyanpeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CTS2019珍珠相关的知识,希望对你有一定的参考价值。

不难发现我们需要一个选奇数/偶数个的egf
这个分别是 $\frac e^x - e^-x 2 $ 和 $\frac e^x + e^-x 2 $。

然后就可以开始推式子了。

答案是

\[ n!\sum _k=0^n-2m(\frac e^x + e^-x 2+y\frac e^x - e^-x 2)^D [x^n][y^k] \]

\[ = n! \frac 12^D \sum _k=0^n-2m \sum _i=0^D e^(2i-D)x (1+y)^i(1-y)^D-i[x^n][y^k] \]

\[ = \frac 12^D \sum_i=0^D \binom Di(2i-D)^n \sum _k=0^n-2m (1+y)^i(1-y)^D-i[y^k] \]

好了,考虑如何计算这个东西。

首先将\((1-y)^D\)计算出来,因为$ (1+y)/(1-y) = 1 + 2y + 2y^2 + 2y^3 + ...$

\(lim = n-2m\)

我们可以轻易的算出贡献

枚举i, 枚举有多少次是2(至少多加了1)

有:
\[ ans*2^D = \sum _i=0^D \binom Di (2i-D)^n \sum_p^D ff[p] \sum_k=0^D \binom lim-pk 2^k \binomik \]

交换第二三个和号,并且将只与一个变量相关的弄到一起,最后会形成如下形式:

\[ ans*2^D = \sum _i=0^D A(i) \sum_p^D B(p) \frac1(i-p)!\sum_k=0^D C(k) \frac1(lim-p-k)! \]

其中,\(A,B,C\)是三个多项式

将sigma_p后的部分当作f(p),f(p)可以通过C与\(e^x\)卷积得到,之后再卷积一次就能得出答案

复杂度一个log

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,g=3;
inline int add(int a,int b)a+=b;return a>=mod?a-mod:a;
inline int sub(int a,int b)a-=b;return a<0?a+mod:a;
inline int mul(int a,int b)return (ll)a*b%mod;
inline int qpow(int a,int b)int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;
const int inv2=qpow(2,mod-2);
/* math */
typedef vector<int> poly;
namespace poly_template
    int rev[4000010];
    void DFT(int *t,int n,int type)
        int l=0;while(1<<l<n)++l;
        for(int i=1;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
        for(int i=0;i<n;i++)if(i<rev[i])swap(t[i],t[rev[i]]);
        for(int step=1;step<n;step<<=1)
            int wn=qpow(g,(mod-1)/(step<<1));
            for(int i=0;i<n;i+=step*2)for(int j=0,w=1;j<step;j++,w=mul(w,wn))
                int x=t[i+j],y=mul(w,t[i+j+step]);
                t[i+j]=add(x,y),t[i+j+step]=sub(x,y);
            
        
        if(type==1)return ;for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
        int inv=qpow(n,mod-2);for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
    
    inline poly NTT(poly A,int n,poly B,int m)
        poly ret;
        int l=0;while(1<<l<n+m)++l;
        A.resize(1<<l),B.resize(1<<l),ret.resize(1<<l);
        DFT(&A[0],1<<l,1);DFT(&B[0],1<<l,1);
        for(int i=0;i<1<<l;i++)ret[i]=mul(A[i],B[i]);
        DFT(&ret[0],1<<l,-1);
        ret.resize(n+m-1);
        return ret;
    
    inline poly NTT(poly A,poly B)return NTT(A,A.size(),B,B.size());

using namespace poly_template;
int D,n,m;

int fac[4000010],ifac[4000010];
inline void binom_init(int n=4000000)
    fac[0]=ifac[0]=1;for(int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
    ifac[n]=qpow(fac[n],mod-2);for(int i=n-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);

inline int binom(int a,int b)
    if(b>a)return 0;
    return mul(fac[a],mul(ifac[b],ifac[a-b]));

poly G,ff,Fac,F;

int main()

    binom_init();
    cin >> D >> n >> m;
    if(n<2*m)printf("%d\n",0);return 0;
    if(D<=n-2*m+1)printf("%d\n",qpow(D,n));return 0;
    ff.resize(D+1);G.resize(D+1);Fac.resize(D+1);F.resize(D+1);
    int lim=n-2*m;
    for(int i=0;i<=min(D,n-2*m);i++)
        ff[i]=binom(D,i);
        if(i&1)ff[i]=mod-ff[i];
        ff[i]=mul(ff[i],fac[lim-i]);
    
    for(int i=0;i<=D;i++)G[i]=mul(qpow(2,i),mul(ifac[i],ifac[i])), Fac[i]=ifac[i];
    ff=NTT(ff,Fac);
    for(int i=0;i<=D;i++)G[i]=mul(G[i],lim-i>=0?ff[lim-i]:0);
    for(int i=0;i<=D;i++)F[i]=mul(mul(fac[D],ifac[D-i]),qpow(1ll*(mod+2*i-D)%mod,n));
    G=NTT(Fac,G);
    int ans=0;
    for(int i=0;i<=D;i++)
        ans=add(ans,mul(F[i],G[i]));
    
    ans=mul(ans,qpow(inv2,D));
    cout << ans << endl;
    return 0;

以上是关于CTS2019珍珠的主要内容,如果未能解决你的问题,请参考以下文章

loj3120CTS2019珍珠

loj3120. 「CTS2019 | CTSC2019」珍珠

luogu P5401 [CTS2019]珍珠

luogu P5401 [CTS2019]珍珠

CTS测试CtsWindowManagerDeviceTestCases模块的testShowWhenLockedImeActivityAndShowSoftInput测试fail项解决方法(代码片段

CTS2019 获奖名单分析-信息学强省强校排行榜!