• HDU6061 RXD and functions【NTT】


    (RXD and functions)

    Problem Description
    RXD has a polynomial function (f(x)), (f(x)=sum ^{n}_{i=0}c_ix_i)
    RXD has a transformation of function (Tr(f,a)), it returns another function g, which has a property that (g(x)=f(x−a)).
    Given (a_1,a_2,a_3,…,a_m), RXD generates a polynomial function sequence (g_i), in which (g_0=f) and (g_i=Tr(g_{i−1},a_i))
    RXD wants you to find (g_m), in the form of (sum ^{m}_{i=0}b_ix_i)
    You need to output bi module (998244353.)
    (n≤10^5)

    Input
    There are several test cases, please keep reading until EOF.
    For each test case, the first line consists of (1) integer (n), which means (deg F).
    The next line consists of (n+1) intergers (c_i)(0 le ci<998244353), which means the coefficient of the polynomial.
    The next line contains an integer (m), which means the length of (a).
    The next line contains (m) integers, the (i) - th integer is (a_i).
    There are (11) test cases.
    (0le ai<998244353)
    (sum mle10^5)

    Output
    For each test case, output an polynomial with degree n, which means the answer.

    Sample Input
    2
    0 0 1
    1
    1

    Sample Output
    1 998244351 1
    Hint
    ((x - 1) ^ 2 = x^2 - 2x + 1)

    题解:
    显然最终操作完的式子为(sum_{i=0}^{n}c_i(x-sum_{i-1}^{m}a_i)^i)
    现在我们记((-sum_{i=1}^{m}a_i)\%MOD=a)
    然后变成这样:
    (sum_{i=0}^{n}c_i(x-a)^i)
    接下来我们对式子进行二项式展开:
    (sum_{i=0}^{n}sum_{j=i}^{n}C(j,j-i)c_jcdot a^{j-i}cdot x^i)
    (j=j-i)替换(j)
    (sum_{i=0}^{n}sum_{j=0}^{n-i}C(j+i,j)cdot c_{j+i}cdot a^jcdot x^j)
    把组合数展开:
    (sum_{i=0}^{n}sum_{j=0}^{n-i}frac{(i+j)!}{i!cdot j!}c_{i+j}cdot a^jcdot x^j)
    整理一下,把和内层求和无关的提到外面来得到:
    (sum_{i=0}^{n}frac{x^i}{i!}sum_{j=0}^{n-i}c_{i+j}cdot (i+j)!cdotfrac{a^j}{j!})
    现在我们先怎么转化里面的式子,使之变成卷积的形式:
    (sum_{j=0}^{n-i}c_{i+j}cdot (i+j)!cdotfrac{a^j}{j!})
    (j+k=n-i)来做替换:
    (Rightarrow sum_{j+k=n-i} c_{n-k}cdot (n-k)!cdot frac{a^j}{j!})
    发现这个式子就是卷积的形式了
    (A[n]=sum c_{n-i}cdot (n-i)!)
    (B[n]=sum frac{a^i}{i!})

    (NTT)来搞即可

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e6+7;
    using LL = int_fast64_t;
    const LL MOD = 998244353;
    const LL g = 3;
    int n,limit,m,l,r[MAXN];
    LL fact[MAXN],rfact[MAXN],c[MAXN],A[MAXN],B[MAXN];
    LL qpow(LL a, LL b){
        LL ret = 1;
        while(b){
            if(b&1) ret = ret * a % MOD;
            b >>= 1;
            a = a * a % MOD;
        }
        return ret;
    }
    LL inv(LL x){ return qpow(x,MOD-2); }
    void NTT(LL arr[], int rev){
        for(int i = 0; i < limit; i++) if(i<r[i]) swap(arr[i],arr[r[i]]);
        for(int len = 1; len < limit; len <<= 1){
            LL wn = qpow(g,(MOD-1)/(len<<1));
            if(rev==-1) wn = inv(wn);
            for(int R = 0; R < limit; R += (len<<1)){
                LL w = 1;
                for(int i = R; i < R + len; i++){
                    LL x = arr[i];
                    LL y = w * arr[i+len] % MOD;
                    arr[i] = (x+y)%MOD;
                    arr[i+len] = (x-y+MOD)%MOD;
                    w = w * wn % MOD;
                }
            } 
        }
    }
    void solve(){
        LL a = 0;
        for(int i = 0; i <= n; i++) scanf("%I64d",&c[i]);
        scanf("%d",&m);
        for(int i = 1; i <= m; i++){
            int x; scanf("%d",&x);
            a -= x;
            if(a<0) a += MOD;
        }
        limit = 1, l = 0;
        while(limit<=(n<<1)) limit <<= 1, l++;
        for(int i = 0; i < limit; i++) r[i] = ((r[i>>1]>>1) | ((i&1)<<(l-1)));
        LL powa = 1;
        for(int i = 0; i < limit; i++){
            if(i<=n){
                A[i] = fact[n-i] * c[n-i] % MOD;
                B[i] = powa * rfact[i] %MOD;
                powa = powa * a % MOD;
            }
            else A[i] = B[i] = 0;
        }
        NTT(A,1); NTT(B,1);
        for(int i = 0; i < limit; i++) A[i] = A[i] * B[i] % MOD;
        NTT(A,-1);
        for(int i = 0; i < limit; i++) A[i] = A[i] * inv(limit) % MOD;
        for(int i = 0; i <= n; i++) printf("%I64d ",A[n-i]*rfact[i]%MOD); puts("");
    }
    int main(){
        fact[0] = 1; for(int i = 1; i < MAXN; i++) fact[i] = i * fact[i-1] % MOD;
        rfact[MAXN-1] = inv(fact[MAXN-1]);
        for(int i = MAXN - 2; i >= 0; i--) rfact[i] = rfact[i+1] * (i+1) % MOD;
        while(scanf("%d",&n)!=EOF) solve();
        return 0;
    }
    
  • 相关阅读:
    Android 高仿微信支付密码输入控件
    ListView用法总结
    我的感悟
    Android Scroll分析——滑动效果产生
    如何查看Android的Keystore文件的SHA1值
    Android 事件拦截机制一种粗鄙的解释
    Android 自定义ViewGroup
    Android 自定义View 总结
    Android 自定义View 三板斧之三——重写View来实现全新控件
    Android 自定义View 三板斧之二——组合现有控件
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12599137.html
Copyright © 2020-2023  润新知