• HDU 6061 RXD and functions


    题目链接:HDU-6061

    题意:给定f(x),求f(x-A)各项系数。

    思路:推导公式有如下结论:

    然后用NTT解决即可。

    代码:

    #include <set>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    typedef long long LL;
    const LL MAXN=1000000;
    const LL MOD=998244353;
    
    // NTT
    // O(nlogn)
    // Verified!
    const LL P = MOD;
    const LL G = 3;
    const LL NUM = 30;
    
    LL  wn[NUM];
    LL A[MAXN], B[MAXN];
    
    LL quick_mod(LL a, LL b, LL m)
    {
        LL ans = 1;
        a %= m;
        while(b)
        {
            if(b & 1)
            {
                ans = ans * a % m;
                b--;
            }
            b >>= 1;
            a = a * a % m;
        }
        return ans;
    }
    
    void GetWn()
    {
        for(LL i=0; i<NUM; i++)
        {
            LL t = 1 << i;
            wn[i] = quick_mod(G, (P - 1) / t, P);
        }
    }
    
    void Prepare(char A[], char B[], LL a[], LL b[], LL &len)
    {
        len = 1;
        LL len_A = strlen(A);
        LL len_B = strlen(B);
        while(len <= 2 * len_A || len <= 2 * len_B) len <<= 1;
        for(LL i=0; i<len_A; i++)
            A[len - 1 - i] = A[len_A - 1 - i];
        for(LL i=0; i<len - len_A; i++)
            A[i] = '0';
        for(LL i=0; i<len_B; i++)
            B[len - 1 - i] = B[len_B - 1 - i];
        for(LL i=0; i<len - len_B; i++)
            B[i] = '0';
        for(LL i=0; i<len; i++)
            a[len - 1 - i] = A[i] - '0';
        for(LL i=0; i<len; i++)
            b[len - 1 - i] = B[i] - '0';
    }
    
    void Rader(LL a[], LL len)
    {
        LL j = len >> 1;
        for(LL i=1; i<len-1; i++)
        {
            if(i < j) swap(a[i], a[j]);
            LL k = len >> 1;
            while(j >= k)
            {
                j -= k;
                k >>= 1;
            }
            if(j < k) j += k;
        }
    }
    
    void NTT(LL a[], LL len, LL on)
    {
        Rader(a, len);
        LL id = 0;
        for(LL h = 2; h <= len; h <<= 1)
        {
            id++;
            for(LL j = 0; j < len; j += h)
            {
                LL w = 1;
                for(LL k = j; k < j + h / 2; k++)
                {
                    LL u = a[k] % P;
                    LL t = w * (a[k + h / 2] % P) % P;
                    a[k] = (u + t) % P;
                    a[k + h / 2] = ((u - t) % P + P) % P;
                    w = w * wn[id] % P;
                }
            }
        }
        if(on == -1)
        {
            for(LL i = 1; i < len / 2; i++)
                swap(a[i], a[len - i]);
            LL Inv = quick_mod(len, P - 2, P);
            for(LL i = 0; i < len; i++)
                a[i] = a[i] % P * Inv % P;
        }
    }
    
    void Conv(LL a[], LL b[], LL n)
    {
        NTT(a, n, 1);
        NTT(b, n, 1);
        for(LL i = 0; i < n; i++)
            a[i] = a[i] * b[i] % P;
        NTT(a, n, -1);
    }
    
    // 快速幂
    // 求x^n%mod
    // Verified!
    LL powMod(LL x,LL n,LL mod)
    {
        LL res=1;
        while(n>0)
        {
            if(n&1) res=res*x % mod;
            x=x*x % mod;
            n>>=1;
        }
        return res;
    }
    // 求逆元
    // a和m应该互质
    // 根据欧拉定理:a的逆即a^(phi(m)-1)
    LL inv(LL a,LL m)
    {
        return powMod(a,m-2,m);
        // return powMod(a,eularPhi(m)-1,m);
    }
    LL mi[MAXN],invsum[MAXN],fac[MAXN];
    LL c[MAXN];
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        GetWn();
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            n++;
            for(int i=0;i<n;i++) scanf("%lld",&c[i]);
            int m,s=0;
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            {
                int tmp;
                scanf("%d",&tmp);
                s=(s+tmp)%MOD;
            }
            int len=1;
            while(len<2*n) len*=2;
            mi[0]=fac[0]=invsum[0]=invsum[1]=1;
            for(int i=1;i<n;i++)
                mi[i]=mi[i-1]*(P-s)%MOD;
            for(int i=1;i<n;i++)
                fac[i]=fac[i-1]*i%MOD;
            for(int i=2;i<n;i++)
                invsum[i]=inv(fac[i],MOD);
            for(int i=0;i<n;i++)
                A[i]=mi[i]*invsum[i]%MOD;
            for(int i=0;i<n;i++)
                B[i]=c[n-i-1]*fac[n-i-1]%MOD;
            for(int i=n;i<len;i++)
                A[i]=B[i]=0;
            Conv(A, B, len);
            for(int i=0;i<n;i++)
                printf("%lld ",A[n-i-1]*invsum[i]%MOD);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 1007 HNOI2008 水平可见的直线
    BZOJ 3155 Preprefix sum
    BZOJ 1036 ZJOI2008 树的统计
    BZOJ 1096 ZJOI2007 仓库建设
    BZOJ 1012 JSOI2008 最大数maxnumber
    BZOJ 1001 狼抓兔子
    BZOJ 1046 HAOI 上升序列
    [POI2015]PUS
    [NOI2011]道路修建
    POI 2015 KIN
  • 原文地址:https://www.cnblogs.com/zarth/p/7301392.html
Copyright © 2020-2023  润新知