[NTT] [HDU5829] Rikka with Subset

题目传送门
接着翻译:
题目描述 Description

我们都知道,六花同学数学不好,勇太君担心这个状况,所以他给了六花酱一些数学问题作为练习,这里有其中的一道题:
勇太君有 n n n个数字 A [ 1 ] A[1] A[1]~ A [ n ] A[n] A[n],还有一个数字 K K K。对于任意一个 A A A的非空子集 S S S S S S的价值等于 S S S集合中最大的 min ⁡ ( ∣ S ∣ , K ) \min(|S|,K) min(S,K)个数之和(译者注: ∣ S ∣ |S| S表示集合 S S S的大小),数组 A A A的价值为所有 A A A的非空子集的价值和。
现在勇太君给出了这 n n n个数,他想知道对任意 K K K属于 [ 1 , n ] [1,n] [1,n]的数组的价值。
这对于Rikka童鞋太难了。你能帮助她吗?

输入 Input

第一行包含一个数字 t ( 1 ≤ t ≤ 10 ) t(1\le t\le 10) t(1t10),表示数据组数。
对于每组数据,第一行有一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le 10^5) n(1n105),表示勇太君有的数字。第二行包含 n n n个数 A [ 1 ] A[1] A[1]~ A [ n ] ( 0 ≤ A [ i ] ≤ 1 0 9 ) A[n](0\le A[i]\le 10^9) A[n](0A[i]109)

输出 Output

对于每组数据,输出一行包含 n n n个整数,第 i i i个数是当 K = i K=i K=i时的数组价值。这个答案会非常大,所以你只需输出答案对 998244353 998244353 998244353取模的结果。

PoPoQQQ:“对于模一个数的计数问题只能用NTT。”
推一下公式。因为是前 min ⁡ ( ∣ S ∣ , K ) \min(|S|,K) min(S,K)大,所以集合中没有 K K K个数的话其余补 0 0 0即可。
先将 A [ i ] A[i] A[i]从大到小排序,我们就可以分开计算一个数 A [ i ] A[i] A[i]的贡献了,这里的贡献指对所有集合的贡献。
因为 A [ i ] A[i] A[i]需要作为集合中第 k k k大出现,所以这个集合至少有 k − 1 k-1 k1个数,比 A [ i ] A[i] A[i]大的选择 k − 1 k-1 k1个进入集合,剩下比 A [ i ] A[i] A[i]小的可选可不选,这样就是 2 n − i 2^{n-i} 2ni种选择。总结起来,用 f [ k ] f[k] f[k]表示所有数作为集合第 k k k大的总贡献。 f [ k ] f[k] f[k]可表示为:
f [ k ] = ∑ i = k n ( i − 1 k − 1 ) 2 n − i A [ i ] f[k]=\sum\limits_{i=k}^n\binom{i-1}{k-1}2^{n-i}A[i] f[k]=i=kn(k1i1)2niA[i]
嗯这么算是 O ( n 2 ) O(n^2) O(n2)的接着超时……
于是我们对这个式子变下形:
f [ k ] = ∑ i = k n ( i − 1 ) ! ( k − 1 ) ! ( i − k ) ! 2 n − i A [ i ] = 1 ( k − 1 ) ! ∑ i = k n ( i − 1 ) ! ( i − k ) ! 2 n − i A [ i ] = 1 ( k − 1 ) ! ∑ i = 0 n − k ( ( i + k ) − 1 ) ! ( ( i + k ) − k ) ! 2 n − ( i + k ) A [ i + k ] = 1 2 k ( k − 1 ) ! ∑ i = 0 n − k 2 n − i i ! ( i + k − 1 ) ! A [ i + k ] \begin{aligned} f[k]&=\sum\limits_{i=k}^n\frac{(i-1)!}{(k-1)!(i-k)!}2^{n-i}A[i]\\ &=\frac{1}{(k-1)!}\sum\limits_{i=k}^n\frac{(i-1)!}{(i-k)!}2^{n-i}A[i]\\ &=\frac{1}{(k-1)!}\sum\limits_{i=0}^{n-k}\frac{((i+k)-1)!}{((i+k)-k)!}2^{n-(i+k)}A[i+k]\\ &=\frac{1}{2^k(k-1)!}\sum\limits_{i=0}^{n-k}\frac{2^{n-i}}{i!}(i+k-1)!A[i+k] \end{aligned} f[k]=i=kn(k1)!(ik)!(i1)!2niA[i]=(k1)!1i=kn(ik)!(i1)!2niA[i]=(k1)!1i=0nk((i+k)k)!((i+k)1)!2n(i+k)A[i+k]=2k(k1)!1i=0nki!2ni(i+k1)!A[i+k]
诶诶诶 ( i + k − 1 ) ! (i+k-1)! (i+k1)! A [ i + k ] A[i+k] A[i+k]咋这么一样呢……
诶诶诶 n − i + i + k = n + k n-i+i+k=n+k ni+i+k=n+k咋是定值呢……
然后就是卷积的套路了……设 a [ i ] = 2 n − i i ! a[i]=\frac{2^{n-i}}{i!} a[i]=i!2ni b [ i ] = ( i − 1 ) ! A [ i ] b[i]=(i-1)!A[i] b[i]=(i1)!A[i],先把 b b b翻转过来,然后就是卷积了……只不过这次是用NTT完成计算,最后的答案 f [ k ] = a [ n − k ] f[k]=a[n-k] f[k]=a[nk],还应该把系数乘上再求个前缀和。
时间复杂度 O ( t n log ⁡ 2 n ) O(tn\log_2n) O(tnlog2n)
Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值