题目链接:见这里
题意:给你一个A数组。你要输出所有的T[k]。T[k]是指A数组的所有子集中前k大的数的和的和。
解题思路:先从大到小排序,排序之后发现,第i个数对于k的贡献只当它作为集合中最大,第二大…第k大的时候才有。那么我们可以想一个比较暴力的方法,枚举每个i作为集合第k大的贡献,在求个前缀和,就是答案。设f[k]为所有数作为第k大的时候的和,那么有

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 4e5 + 10;
const LL G = 3, P = 998244353; //AC
//const LL G = 3, P = 2281701377; //WA
//const LL G = 3, P = 2748779069441; //WA

LL quick(LL x, LL n) {
    LL ret = 1;
    for(; n; n >>= 1) {
        if(n & 1) ret = ret * x % P;
        x = x * x % P;
    }
    return ret;
}

void rader(LL* y, int len) {
    for(int i = 1, j = len / 2; i < len - 1; i++) {
        if(i < j) swap(y[i], y[j]);
        int k = len / 2;
        while(j >= k) {j -= k; k /= 2;}
        if(j < k) j += k;
    }
}
void ntt(LL* y, int len, int op) {
    rader(y, len);
    for(int h = 2; h <= len; h <<= 1) {
        LL wn = quick(G, (P - 1) / h);
        if(op == -1) wn = quick(wn, P - 2);
        for(int j = 0; j < len; j += h) {
            LL w = 1;
            for(int k = j; k < j + h / 2; k++) {
                LL u = y[k];
                LL t = w * y[k + h / 2] % P;
                y[k] = (u + t) % P;
                y[k + h / 2] = (u - t + P) % P;
                w = w * wn % P;
            }
        }
    }
    if(op == -1) {
        LL inv = quick(len, P - 2);
        for(int i = 0; i < len; i++) y[i] = y[i] * inv % P;
    }
}

LL inv[N], fac[N], f[N], a[N], b[N], A[N];
LL inv2;
int n;

void pre_init(){
    inv2 = quick(2, P - 2);
    inv[0] = inv[1] = 1;
    fac[0] = fac[1] = 1;
    for(LL i = 2; i <= 1e5; i++){
        inv[i] = inv[i-1] * quick(i, P-2) % P;
        fac[i] = fac[i-1] * i % P;
    }
}

void solve1(){ //化成做卷积的两个数组
    for(int i = 0; i < n; i++){
        a[i] = inv[i] * quick(2, n - i) % P;
    }
    for(int i = 1; i <= n; i++){
        b[i] = fac[i-1] * A[i] % P;
    }
    reverse(b+1, b+n+1);
    for(int i = 0; i < n; i++) b[i] = b[i+1];
    b[n] = 0;
}

void solve2(){ //做ntt
    int len = 1;
    while(len <= 2*n) len <<= 1;
    ntt(a, len, 1);
    ntt(b, len, 1);
    for(int i = 0; i < len; i++) a[i] = a[i] * b[i] % P;
    ntt(a, len, -1);
}

void gao(){ //求前缀和,输出答案
    LL r = inv2;
    for(int i = 1; i <= n; i++){
        f[i] = r * inv[i-1] % P * a[n-i] % P;
        f[i] = (f[i-1] + f[i]) % P;
        printf("%lld ", f[i]);
        r = r * inv2 % P; //最后一个数后面还有空格
    }
    printf("\n");
}

int main()
{
    int T;
    pre_init();
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(A, 0, sizeof(A));
        for(int i = 1; i <= n; i++) scanf("%lld", &A[i]);
        sort(A + 1, A + n + 1, greater<LL>());
        solve1();
        solve2();
        gao();
    }
    return 0;
}

没搞懂为什么一定要用这个原根才可以AC。