JZOJ 5666 法力风暴

ai=Ai
注意到 ixai=ni=1aini=1(ai[i=x]),故转化为求 E(ni=1ai),其中 ai 表示 ai 所有操作后的值。

bi=aiai,则有 E(ni=1(aibi))=1nkb1+b2++bn=kk!ni=1bi!ni=1(aibi)=k!nkb1+b2++bn=kni=1aibibi!

如果有点生成函数知识的话,容易发现这很像某些生成函数之积的 xk 项系数。
设指数生成函数 Gi(x)=j=1aijj!xj
容易发现 Gi(x)=ex(aix)
b1+b2++bn=kni=1aibibi!=(ni=1Gi(x))[xk]

然后发现 ni=1Gi(x)=enxni=1(aix)
考虑用普通的分治思想 + NTT 来求 ni=1(aix)(并不是 CDQ 分治)。
(大常数选手被卡)

又因为 enx=i=0nixii!,得 (ni=1Gi(x))[xk]=ni=0nki(ki)!fi,其中 fi=(ni=1(aix))[xi]
看起来是不能做的,但是本来还有个系数 k!nk
k!nkni=0nki(ki)!fi=ni=0k!nk(ki)!fi

注意到 k!(ki)! 只有 i 项,于是直接算即可(其实就是下降幂)
实际上 ni=1ai=f0,故要求的为 ni=1k!nk(ki)!fi

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector","inline")
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1 << 18;
const int mod = 998244353;
const int G = 3;
const int Gi = 332748118;
int len,n = 1,k;
int fpow(int a,int b)
{
int ret = 1;
for(;b;b >>= 1)
(b & 1) && (ret = (long long)ret * a % mod),a = (long long)a * a % mod;
return ret;
}
int a[N + 5],f[N + 5],omg[N + 5],inv[N + 5];
int ans;
void ntt(int *a,int *omg,int n,int lg)
{
for(register int i = 0;i < n;++i)
{
int t = 0;
for(register int j = 0;j < lg;++j)
if(i & (1 << j))
t |= (1 << lg - j - 1);
if(i < t)
swap(a[i],a[t]);
}
for(register int w = 2,m = 1;w <= n;w <<= 1,m <<= 1)
for(register int i = 0;i < n;i += w)
for(register int j = 0;j < m;++j)
{
int t = (long long)omg[n / w * j] * a[i + j + m] % mod;
a[i + j + m] = (a[i + j] - t + mod) % mod,a[i + j] = (a[i + j] + t) % mod;
}
}
void mul(int *a,int *b,int len)
{
int lg = 0,n = 1;
for(;n < len * 2;n <<= 1,++lg);
for(register int i = 0;i < n;++i)
omg[i] = fpow(G,(mod - 1) / n * i),inv[i] = fpow(Gi,(mod - 1) / n * i);
ntt(a,omg,n,lg),ntt(b,omg,n,lg);
for(register int i = 0;i < n;++i)
a[i] = (long long)a[i] * b[i] % mod;
ntt(a,inv,n,lg);
int n_inv = fpow(n,mod - 2);
for(register int i = 0;i < n;++i)
a[i] = (long long)a[i] * n_inv % mod;
}
void solve(int l,int r,int L,int R)
{
if(l == r)
{
if(l < len)
f[L] = a[l] % mod,f[L + 1] = mod - 1;
else
f[L] = 1,f[L + 1] = 0;
return ;
}
int mid = l + r >> 1,MID = L + R >> 1;
solve(l,mid,L,MID);
solve(mid + 1,r,MID + 1,R);
static int buf[2][N + 5];
for(register int i = 0;i <= R - L;++i)
buf[0][i] = buf[1][i] = 0;
for(register int i = 0;i <= mid - l + 1;++i)
buf[0][i] = f[L + i],buf[1][i] = f[MID + 1 + i];
mul(buf[0],buf[1],mid - l + 2);
for(register int i = 0;i <= r - l + 1;++i)
f[L + i] = buf[0][i];
}
int main()
{
freopen("manastorm.in","r",stdin),freopen("manastorm.out","w",stdout);
scanf("%d%d",&len,&k),k %= mod;
for(;n < len;n <<= 1);
for(register int i = 0;i < len;++i)
scanf("%d",a + i);
solve(0,n - 1,0,2 * n - 1);
int n_inv = fpow(len,mod - 2);
for(register int i = 1,prod = (long long)n_inv * k % mod;i <= len;prod = (long long)prod * n_inv % mod * (k - i) % mod,++i)
ans = (ans - (long long)f[i] * prod % mod + mod) % mod;
printf("%d\n",ans);
}

Related Issues not found

Please contact @Alpha1022 to initialize the comment