Rikka with Subset ( NTT 练习)

 题目: http://acm.hdu.edu.cn/showproblem.php?pid=5829

  Rikka with Subset ( NTT 练习)

 

 Rikka with Subset ( NTT 练习)

 

Rikka with Subset ( NTT 练习)

 

 

参考   https://blog.csdn.net/hdxrie/article/details/80961416?utm_source=blogxgwz3

Rikka with Subset ( NTT 练习)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define LL long long
#define ULL unsigned long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define dep(i,j,k) for(int i=k;i>=j;i--)
#define INF 0x3f3f3f3f
#define mem(i,j) memset(i,j,sizeof(i))
#define make(i,j) make_pair(i,j)
#define pb push_back
using namespace std;
const LL p = 998244353, N = (1 << 18) + 5, G = 3, Gi = 332748118;
LL ksm(LL a,LL b) {
    LL ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}
int n, m;
LL limit, a[N], b[N], r[N], l;
void NTT(LL *A, int type) {
    rep(i, 0, limit - 1) if(i < r[i]) swap(A[i], A[r[i]]);
    for(int mid = 1; mid < limit; mid <<= 1) {
        LL Wn = ksm(type == 1 ? G : Gi, (p - 1) / (mid << 1) );
        for(int j = 0;j < limit; j += (mid << 1)) {
            LL w = 1;
            for(int k = 0; k < mid; k++, w = (w * Wn) % p) {
                int x = A[j + k], y = w * A[j + k + mid] % p;
                A[j + k] = ( x + y ) % p;
                A[j + k + mid] = (x - y + p) % p;
            }
        }
    }
    if (type == -1) {
        LL inv = ksm(limit, p - 2);
        for (int i = 0; i < limit; i++) A[i] = 1ll * A[i] * inv % p;
    }
}
LL inv[N], fac[N], invfac[N];
void init() {
    invfac[0] = fac[0] = inv[1] = fac[1] = invfac[1] = 1LL;
    rep(i, 2, N - 1) {
        fac[i]=(fac[i-1]*i)%p;
        inv[i] = (p - p / i) * inv[p % i] % p;
        invfac[i] = (invfac[i - 1] * inv[i]) % p;
    }
}
LL A[N];
int main() {
    init();
    int t;
    scanf("%d", &t);
    while( t-- ) {
        scanf("%d", &n);
        mem(a, 0); mem(b, 0);
        for (limit = 1, l = 0; limit <= (n << 1); l++, limit <<= 1);
        rep(i, 0, limit - 1) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
        rep(i, 0, n - 1) scanf("%lld", &A[i]);
        sort(A, A + n,greater<LL>());
        rep(i, 0, n - 1) a[i] = ksm(2, n - i) * invfac[i] % p;
        rep(i, 0, n - 1) b[i] = fac[i] * A[i] % p;
        reverse(b, b + n);
        NTT(a, 1); NTT(b, 1);
        rep(i, 0, limit - 1) a[i] = a[i] * b[i] % p;
        NTT(a, -1);
        LL ans = 0LL, preans = 0LL; LL coe = inv[2];
        rep(i, 1, n) {
            ans = coe * invfac[i-1] % p * a[n-i] % p;
            ans = (ans + preans) % p;
            printf("%lld ",ans);
            coe = coe * inv[2] % p; swap(ans, preans);
        }
        puts("");
    }
    return 0;
}
/*#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN (1<<18)+5
#define MOD 998244353LL
#define g 3LL
using namespace std;
int n,m,L,T,A[MAXN],rev[MAXN];
long long inv[MAXN],fac[MAXN],invfac[MAXN];
long long a[MAXN],b[MAXN];
long long ans_i,pre_ans_i,coe;

inline bool cmp(long long a,long long b){return a>b;}

inline long long Quick_MOD(long long a,long long b)
{
    long long res=1,base=a;
    while (b)
    {
        if (b&1) res=(res*base)%MOD;
        base=(base*base)%MOD;
        b>>=1;
    }
    return res;
}

inline void NTT(long long c[],int n,int f)
{
    long long w,wn,x,y;
    for (int i=0;i<n;i++)
        if (i<rev[i]) swap(c[i],c[rev[i]]);
    for (int i=1;i<n;i<<=1)
    {
        wn=Quick_MOD(g,(MOD-1)/(i<<1));
        if (!~f) wn=Quick_MOD(wn,MOD-2);
        for (int p=i<<1,j=0;j<n;j+=p)
        {
            w=1LL;
            for (int k=0;k<i;k++,w=w*wn%MOD)
            {
                x=c[j+k];y=c[j+k+i]*w%MOD;
                c[j+k]=(x+y)%MOD;c[j+k+i]=(x-y+MOD)%MOD;
            }
        }
    }
    if (!~f)
        for (int i=0;i<n;i++) c[i]=c[i]*inv[n]%MOD;
    return ;
}

inline void PreWork()
{
    invfac[0]=fac[0]=inv[1]=fac[1]=invfac[1]=1LL;
    for (int i=2;i<MAXN;i++)
    {
        fac[i]=(fac[i-1]*i)%MOD;
        inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
        invfac[i]=(invfac[i-1]*inv[i])%MOD;
    }
    return ;
}

inline void read(int &x)
{
    x=0;char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return ;
}

int main()
{
    PreWork();
    read(T);
    while (T--)
    {
        memset(a,0,sizeof a);memset(b,0,sizeof b);
        read(n);
        for (m=1,L=0;m<=(n<<1);L++,m<<=1);
        for (int i=0;i<m;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
        for (int i=0;i<n;i++) read(A[i]);
        sort(A,A+n,cmp);
        for (int i=0;i<n;i++) a[i]=Quick_MOD(2,n-i)*invfac[i]%MOD;
        for (int i=0;i<n;i++) b[i]=fac[i]*(long long)A[i]%MOD;
        reverse(b,b+n);
        NTT(a,m,1);NTT(b,m,1);
        for (int i=0;i<m;i++) a[i]=a[i]*b[i]%MOD;
        NTT(a,m,-1);
        ans_i=pre_ans_i=0LL;coe=inv[2];
        for (int i=1;i<=n;i++)
        {
            ans_i=coe*invfac[i-1]%MOD*a[n-i]%MOD;
            ans_i=(ans_i+pre_ans_i)%MOD;
            printf("%lld ",ans_i);
            coe=coe*inv[2]%MOD;swap(ans_i,pre_ans_i);
        }
        putchar('\n');
    }
    return 0;
}*/
View Code

 

上一篇:131. 分割回文串


下一篇:(按位)MySQL中的Supersets和Subsets