在你的帮助下,跳蚤国王终于打开了最后一间房间的大门。然而,picks 博士和他的猴子们早已通过地道逃跑了。万幸的是,因为阿姆斯特朗回旋加速喷气式阿姆斯特朗炮本身太过笨重,无法从地道中运走,所以还被静静的停放在房间的正中央。
拥有了征服世界的力量,跳蚤国王感觉非常一颗赛艇。为了试验这个传说中的武器的威力,跳蚤国王让士兵们把炮口对准空无一人的实验室开炮。
然而,事情总是没有这么顺利。片刻之后,一个士兵匆匆跑到跳蚤国王身前:“报!picks 博士给它设置了保险!但是我们根本不知道解除方法!”
经过研究,跳蚤国王发现,picks 博士所设置的保险措施可以简化为这样一个问题:
首先炮身的屏幕上显示了 个数,接着在模 ,一个质数) 意义下,给出了 条指令,每一条指令都是下列两种之一:
- 给所有数加上某一个数。
- 让所有数都变成原来的逆元。(保证这时所有数的逆元都存在)
在每个指令完成之后,你要回答当前屏幕上所有数的和。
跳蚤国王思索了片刻,发现这个问题奥妙重重,于是他让你——这附近最著名的民间科学家来帮他解决这个难题。
输入格式
第一行两个正整数 ,含义如题意所述。
第二行个数,表示屏幕上最初显示的 个数。
接下来行,表示 条指令,第 行第一个数表示第 个操作的类型。
若 则接下来有一个整数 ,表示给所有数都加上 。
若 则表示将所有数都变成原来的逆元。
输出格式
输出行,第行一个整数表示第条指令之后当前屏幕上每个数的和。
样例一
input
5 5
1 2 3 4 5
1 1
2
1 1
2
2
output
20
349385525
349385530
292342993
349385530
explanation
执行每个指令后的数列分别如下:
2 3 4 5 6
499122177 332748118 748683265 598946612 166374059
499122178 332748119 748683266 598946613 166374060
665496236 249561089 399297742 831870295 142606337
499122178 332748119 748683266 598946613 166374060
限制与约定
测试点编号 | 限制与约定 |
---|---|
1 | $n, m \leq 1000$ |
2 | $n \leq 100000$, $m \leq 60000$, $t_i = 1$ |
3 | $n, m \leq 10000$ |
4 | $n, m \leq 20000$ |
5 | $n, m \leq 30000$ |
6 | $n \leq 100000$, $m \leq 30000$ |
7 | |
8 | $n \leq 100000$, $m \leq 60000$ |
9 | |
10 |
对于所有数据,, 其他所有数均为区间中的整数。
保证任何时候每个数的逆元均存在。
时间限制: 空间限制:
题解
出门左拐UOJ; 那一毫秒的距离
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1e6 * 4;
const int MOD = 998244353;
const int L = (1 << 18) + 1;
const int LM = (1 << 16) + 1;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int N, Inv, rev[MAXN];
int Sum = 0, n, m;
struct data
{
int e, f, g, id;
}s[60005];
long long pow_mod(long long a, int b)
{
long long ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ans;
}
int ans[MAXN], cnt;
void insert(int a, int b, int c, int d, int id)
{
if (b == 0)
{
ans[id] = ((1ll * a * Sum) + (1ll * c * n)) % MOD * pow_mod(d, MOD - 2) % MOD;
return;
}
s[++cnt].f = (1ll * b * c - 1ll * a * d) % MOD;
b = pow_mod(b, MOD - 2);
s[cnt].e = 1ll * a * b % MOD, s[cnt].g = 1ll * d * b % MOD;
b = 1ll * b * b % MOD; s[cnt].f = 1ll * s[cnt].f * b % MOD;
if (s[cnt].f < 0) s[cnt].f += MOD;
s[cnt].id = id;
}
void Init(int x)
{
N = 1;
while (N < (x << 1)) N <<= 1;
Inv = pow_mod(N, MOD - 2);
for (int i = 1; i < N; i++)
if (i & 1)
rev[i] = (rev[i >> 1] >> 1) | (N >> 1);
else
rev[i] = (rev[i >> 1] >> 1);
}
inline int Calc(int x)
{
N = 1;
while (N < (x << 1)) N <<= 1;
return N;
}
void FFt(int *a, int op)
{
int w, wn, t;
for (int i = 0; i < N; i++)
if (i < rev[i])
swap(a[i], a[rev[i]]);
for (int k = 2; k <= N; k <<= 1)
{
wn = pow_mod(3, op == 1 ? (MOD - 1) / k : MOD - 1 - (MOD - 1) / k);
for (int j = 0; j < N; j += k)
{
w = 1;
for (int i = 0; i < (k >> 1); i++, w = 1ll * w * wn % MOD)
{
t = 1ll * a[i + j + (k >> 1)] * w % MOD;
a[i + j + (k >> 1)] = (a[i + j] - t + MOD) % MOD;
a[i + j] = (a[i + j] + t) % MOD;
}
}
}
if (op == -1)
for (int i = 0; i < N; i++)
a[i] = 1ll * a[i] * Inv % MOD;
}
int tmp[MAXN], x[MAXN];
void Get_Inv(int *a, int *b, int n)
{
if (n == 1) return b[0] = pow_mod(a[0], MOD - 2), void();
Get_Inv(a, b, n + 1 >> 1);
Init(n);
for (int i = 0; i < n; i++) tmp[i] = a[i];
for (int i = n; i < N; i++) tmp[i] = 0;
FFt(tmp, 1), FFt(b, 1);
for (int i = 0; i < N; i++)
b[i] = 1ll * b[i] * ((2 - 1ll * b[i] * tmp[i] % MOD + MOD) % MOD) % MOD;
FFt(b, -1);
for (int i = n; i < N; i++) b[i] = 0;
}
int Get_mod(int *a, int ra, int *b, int rb, int *c)
{
while (ra && !a[ra - 1]) --ra;
while (rb && !b[rb - 1]) --rb;
if (ra < rb)
{
memcpy (c, a, ra << 2);
memset (c + ra, 0, (rb - ra) << 2);
return rb;
}
static int tmp1[MAXN], tmp2[MAXN];
int rc = ra - rb + 1;
int l = Calc(rc);
for (int i = 0; i < l; i++) tmp1[i] = 0;
reverse_copy(b, b + rb, tmp1);
for (int i = 0; i < l; i++) tmp2[i] = 0;
// for (int i = 0; i < rb; i++) printf ("1: %d, tmp1: %d\n", rb, tmp1[i]);
Get_Inv(tmp1, tmp2, rc);
for (int i = rc; i < l; i++) tmp2[i] = 0;
reverse_copy(a, a + ra, tmp1);
for (int i = rc; i < l; i++) tmp1[i] = 0;
Init(rc), FFt(tmp1, 1), FFt(tmp2, 1);
for (int i = 0; i < N; i++) tmp1[i] = 1ll * tmp1[i] * tmp2[i] % MOD;
FFt(tmp1, -1);
// for (int i = 0; i < rb; i++) printf ("2: %d, tmp1: %d\n", rb, tmp1[i]);
reverse(tmp1, tmp1 + rc);
// for (int i = 0; i < rb; i++) printf ("3: %d, tmp1: %d\n", rb, tmp1[i]);
Init(ra);
for (int i = 0; i < rb; i++) tmp2[i] = b[i];
for (int i = rb; i < N; i++) tmp2[i] = 0;
for (int i = rc; i < N; i++) tmp1[i] = 0;
FFt(tmp1, 1), FFt(tmp2, 1);
for (int i = 0; i < N; i++) tmp1[i] = 1ll * tmp1[i] * tmp2[i] % MOD;
FFt(tmp1, -1);
// for (int i = 0; i < rb; i++) printf ("4: %d, tmp1: %d\n", rb, tmp1[i]);
for (int i = 0; i < rb; i++) c[i] = (a[i] - tmp1[i] + MOD) % MOD;
for (int i = rb; i < N; i++) c[i] = 0;
// for (int i = 0; i < rb; i++) printf ("C: %d, %d\n", rb, c[i]);
while (rb && !c[rb - 1]) --rb;
return rb;
}
int Solve0(int *a, int l, int r)
{
int ra = r - l + 2;
if (ra <= 256)
{
memset(a, 0, ra << 2), a[0] = 1;
for (int i = l; i <= r; i++)
for (int v = x[i], j = i - l; j != -1; j--)
{
a[j + 1] = (a[j + 1] + a[j]) % MOD;
a[j] = 1ll * a[j] * v % MOD;
}
return ra;
}
int mid = l + r >> 1;
int *f1 = a, r1 = Solve0(f1, l, mid);
int *f2 = a + r1, r2 = Solve0(f2, mid + 1, r);
N = 1;
while (N < ra) N <<= 1;
Inv = pow_mod(N, MOD - 2);
for (int i = 1; i < N; i++)
if (i & 1)
rev[i] = (rev[i >> 1] >> 1) | (N >> 1);
else
rev[i] = (rev[i >> 1] >> 1);
static int tmp1[L], tmp2[L];
memcpy(tmp1, f1, r1 << 2), memset (tmp1 + r1, 0, (N - r1) << 2), FFt(tmp1, 1);
memcpy(tmp2, f2, r2 << 2), memset (tmp2 + r2, 0, (N - r2) << 2), FFt(tmp2, 1);
for (int i = 0; i < N; i++) a[i] = 1ll * tmp1[i] * tmp2[i] % MOD;
FFt(a, -1);
return ra;
}
int *p[L];
int sta[MAXN];
int mem[LM << 4], *head = mem;
inline int Solve1(int id, int l, int r)
{
int ra = r - l + 2;
if (ra <= 256)
{
int *f = p[id] = head; head += ra;
memset (f, 0, ra << 2), 0[f] = 1;
for (int i = l; i <= r; i++)
for (int v = (MOD - sta[i]) % MOD, j = i - l; j != -1; j--)
f[j + 1] = (f[j + 1] + f[j]) % MOD, f[j] = 1ll * f[j] * v % MOD;
return ra;
}
int mid = l + r >> 1;
int r1 = Solve1(id << 1, l, mid), *f1 = p[id << 1];
int r2 = Solve1(id << 1 | 1, mid + 1, r), *f2 = p[id << 1 | 1];
N = 1;
while (N < ra) N <<= 1;
Inv = pow_mod(N, MOD - 2);
for (int i = 1; i < N; i++)
if (i & 1)
rev[i] = (rev[i >> 1] >> 1) | (N >> 1);
else
rev[i] = (rev[i >> 1] >> 1);
static int tmp1[LM], tmp2[LM];
memcpy(tmp1, f1, r1 << 2), memset (tmp1 + r1, 0, (N - r1) << 2), FFt(tmp1, 1);
memcpy(tmp2, f2, r2 << 2), memset (tmp2 + r2, 0, (N - r2) << 2), FFt(tmp2, 1);
int *f = p[id] = head; head += ra;
for (int i = 0; i < N; i++) f[i] = 1ll * tmp1[i] * tmp2[i] % MOD;
FFt(f, -1);
return ra;
}
int val0[LM], val[LM];
void Solve2(int id, int *a, int *b, int l, int r, int deg)
{
int ra = r - l + 2;
if (deg <= 256)
{
int F, G;
for (int i = l; i <= r; i++)
{
F = G = 0;
int u = sta[i], v = 1;
for (int j = 0; j <= deg; j++)
{
F = (F + 1ll * v * a[j]) % MOD;
G = (G + 1ll * v * b[j]) % MOD;
v = 1ll * v * u % MOD;
}
val0[i] = F, val[i] = G;
}
return;
}
int mid = l + r >> 1;
int r1 = Get_mod(a, deg, p[id], ra, a + deg); a += deg;
int r2 = Get_mod(b, deg, p[id], ra, b + deg); b += deg;
ra = min(r1, r2);
Solve2(id << 1, a, b, l, mid, ra), Solve2(id << 1 | 1, a, b, mid + 1, r, ra);
}
int g[MAXN], h[MAXN];
int main()
{
// freopen ("1.in", "r", stdin);
// freopen ("1.out", "w", stdout);
n = read(), m = read();
Sum = 0;
for (int i = 1; i <= n; i++)
x[i] = read() % MOD, Sum = (Sum + x[i]) % MOD;
int A = 1, B = 0, C = 0, D = 1;
for (int i = 1; i <= m; i++)
{
if (read() == 1)
{
int v = read() % MOD;
A = (A + 1ll * v * B % MOD) % MOD;
C = (C + 1ll * v * D % MOD) % MOD;
insert(A, B, C, D, i);
}
else
{
swap(A, B);
swap(C, D);
insert(A, B, C, D, i);
}
}
if (cnt)
{
for (int i = 1; i <= cnt; i++) sta[i] = s[i].g;
sort(sta + 1, sta + cnt + 1);
int lenth = unique(sta + 1, sta + cnt + 1) - sta - 1;
for (int i = 1; i <= cnt; i++)
s[i].g = lower_bound(sta + 1, sta + lenth + 1, s[i].g) - sta;
Solve0(g, 1, n);
for (int i = 1; i <= n; i++) h[i - 1] = 1ll * g[i] * i % MOD;
Solve1(1, 1, lenth);
Solve2(1, g, h, 1, lenth, n + 1);
for (int i = 1; i <= cnt; i++)
ans[s[i].id] = (1ll * s[i].e * n % MOD + 1ll * s[i].f * val[s[i].g] % MOD * pow_mod(val0[s[i].g], MOD - 2) % MOD) % MOD;
}
for (int i = 1; i <= m; i++)
printf ("%d\n", ans[i]);
// while (1);
}