[HDU] 6061 RXD and functions [NTT]

来源:互联网 发布:织梦cms在线演示 编辑:程序博客网 时间:2024/06/11 08:42

URL: http://acm.split.hdu.edu.cn/showproblem.php?pid=6061

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 524288/524288
K (Java/Others) Total Submission(s): 702 Accepted Submission(s): 282

Problem Description
RXD has a polynomial function f(x), f(x)=∑ni=0cixi
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 a1,a2,a3,…,am, RXD generates a polynomial function sequence gi, in which g0=f and gi=Tr(gi−1,ai)
RXD wants you to find gm, in the form of ∑mi=0bixi
You need to output bi module 998244353.
n≤105

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 degF.
The next line consists of n+1 intergers ci,0≤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 ai.
There are 11 test cases.
0<=ai<998244353
∑m≤105

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

(x1)2=x22x+1

题解

待求表达式可以拆开然后化成 a(n)=ni=0h(i)g(i) 的形式

注意到只要令 h(x)=h(nx) 就可到一个卷积式 (hg)(n)=ni=0h(ni)g(i)

然后NTT

#include<stdio.h>typedef long long LL;const int MAXN = 1 << 18;const int p    = (119 << 23) + 1;const int g    = 3;const int NUM  = 23;int C[MAXN], A[MAXN], B[MAXN], fac[MAXN], wn[MAXN], n, m, len, S;void swap(int &x, int &y) {    int t = x;    x = y;    y = t;}int mod_pow(int a, int k) {    int res = 1;    while(k) {        if(k&1) res = 1LL * res * a % p;        a = 1LL * a * a % p;        k >>= 1;    }    return res;}void init() {    fac[0] = 1;    for(int i = 1; i < MAXN; ++i) {        fac[i] = 1LL * fac[i - 1] * i % p;    }    for(int i = 0; i < NUM; ++i) {        int t = 1 << i;        wn[i] = mod_pow(g, (p - 1) / t);    }}void rader(int y[]) {    for(int i = 1, j = len >> 1, k; i < len - 1; ++ i) {        if(i < j) swap(y[i], y[j]);        k = len >> 1;        while(j >= k) {            j -= k;            k >>= 1;        }        if(j < k) j += k;    }}void NTT(int y[], int op) {    rader(y);    int id = 0;    for(int h = 2; h <= len; h <<= 1) {        ++id;        for(int i = 0; i < len; i += h) {            int w = 1;            for(int j = i; j < i + h / 2; ++j) {                int u = y[j];                int t = 1LL * w * y[j + h / 2] % p;                y[j] = (u + t) % p;                y[j + h / 2] = (u - t) % p;                w = 1LL * w * wn[id] % p;            }        }    }    if(op == -1) {        for(int i = 1; i < len / 2; ++i) {            swap(y[i], y[len - i]);        }        int inv = mod_pow(len, p - 2);        for(int i = 0; i < len; ++i) {            y[i] = 1LL * y[i] * inv % p;            y[i] += p;            y[i] %= p;        }    }}void slove() {    for(len = 1; len < (n << 1); len <<= 1) ;//  printf("len: %d\n", len);    for(int i = 0; i < len; ++i) {        A[i] = i > n ? 0 : 1LL * C[n - i] * fac[n - i] % p;        B[i] = i > n ? 0 : 1LL * mod_pow(S, i) * mod_pow(fac[i], p - 2) % p;//      printf("#%d %d\n", C[i], B[i]);    }    NTT(A, 1);    NTT(B, 1);    for(int i = 0; i < len; ++i) {        B[i] = 1LL * A[i] * B[i] % p;    }    NTT(B, -1);    int top = len - 1;    while(top && !B[top]) --top;    for(int i = 0; i <= n; ++i) {        int ans = 1LL * B[n - i] * mod_pow(fac[i], p - 2) % p;        printf(i == n ? "%d \n" : "%d ", ans);    }}int main(){    init();    while(scanf("%d", &n) != EOF) {        for(int i = 0; i <= n; ++i) {            scanf("%d", C + i);        }        scanf("%d", &m);        S = 0;        for(int i = 0, a; i < m; ++i) {            scanf("%d", &a);            S -= a;            S += p;            S %= p;        }        slove();    }    return 0;}
原创粉丝点击