zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    TCP为什么是个可靠的协议
    socket网络编程快速上手(二)——细节问题(4)
    socket网络编程快速上手(二)——细节问题(3)
    socket网络编程快速上手(二)——细节问题(2)
    socket网络编程快速上手(二)——细节问题(1)
    socket网络编程快速上手(一)
    多线程编程中使用pthread_create内存泄露问题
    股市量化智能分析2035
    忘记mysql root密码的解决方法
    CentOS 下快速安装部署Nginx网站
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12599137.html
Copyright © 2011-2022 走看看