胡闹 交互程序

毒瘤交互。

题目大意

有$N$个盒子,第$i$个盒子里面有$p_i$个球,从一个盒子中只能拿一个球出来。求恰好拿出来$M$个球的方案数,对$998244353$取模。

你不知道$pi​$的具体的值,只能指定操作。

具体来说,你有一个长度为$T$的整型数组$A$,其中前$N$个位置初始存的是$p_1,p_2,⋯,p_N$。其余位置的初始值由你通过Set操作来决定。

在决定完初始值之后,你就只能指定操作了。你只能提出:

  1. $A_i=A_j+A_k$
  2. $A_i=A_j−A_k$
  3. $A_i=A_j\times A_k$(所有运算均在模$998244353$意义下)
  4. 过程中不允许你修改前$N$个位置的值。
  5. 过程中不允许使用Set操作赋值。

你还需要指出$A$中的哪一个数是答案。

数据范围

$1\le M\le N\le 1000,T=1004$

解析

由生成函数,答案显然为:
$$
Ans=\prod_{i=1}^n (1+p_i\times x) [x^{n-m}]
$$
然后我们考虑一些事情:

操作的处理

归零

直接把一个数减去自身即可。

归一

费马小定理即可。
$$
a^{P-1}\equiv1(\bmod P)
$$

复制

先归零,然后加起来即可。

(计算中)赋值

在计算前,先搞一个$1$出来。

把要赋的值二进制分解赋值即可。

优化

直接搞暴力复杂度有点爆炸。

考虑一下$IDFT$的过程,那么我们可以把答案化成这样的形式:
$$
Ans=\frac{1}{N}\times\sum_{i=0}^{N-1}f(\omega_N^i)\times\omega_N^{-i\times m}
$$
这个时候我们就发现$T=1004$给我们剩下了哪$4$个变量了:
$$
Ans,f(x),x,y=1
$$

实现时预处理出$\omega_N^i$即可。

Notice

哎呀这个东西时真的坑。

我被我的巨大常数送走无数次之后,决心:

让常数优化成为习惯。

然后我就疯狂加inline,然后就疯狂Complie Error

调了好久,最后原因是交互库你里面的函数没有inline,而我加了。

这样会导致什么呢?对,交互库的函数就没有定义了。

而且这个东西不用g++ -o %< % grader.cpp还查不出来。

难受😔。

Code

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
#define REP(i, s, e) for (int i = s; i <= e; i++)

#include <bits/stdc++.h>
#include "polynomial.h"
using namespace std;
const int maxn = 1000 + 30, g = 3, MOD = 998244353;
int n, m, t, N = 1 << 10;
int ans, fx, w[maxn], t1, t2;

inline int power_pow(int a, int b)
{
int ans = 1, base = a;
while (b)
{
if (b & 1) ans = 1ll * ans * base % MOD;
base = 1ll * base * base % MOD;
b >>= 1;
}
return ans;
}

void Init(int n, int m, int t)
{
::n = n;
::m = n - m;
N = 1024;
Set(ans = n + 4, 0);
Set(fx = n + 1, 0);
Set(t1 = n + 2, 1);
Set(t2 = n + 3, 1);
w[0] = 1;
w[1] = power_pow(3, (MOD - 1) / N);
REP(i, 2, N - 1) w[i] = 1ll * w[i-1] * w[1] % MOD;
}

inline void Set_Zero(int x) {Minus(x, x, x);}
inline void Copy(int i,int j)
{
Set_Zero(i);
Plus(i, i, j);//i = i + j = 0 + j = j
}
inline void Power_pow(int base, int b)
{
bool first = 1;
while (b)
{
if (b & 1)
if (first)
{
first = 0;
Copy(t1, base);
}
else Multiply(t1, t1, base);
Multiply(base, base, base);
b >>= 1;
}
Copy(base, t1);
}
inline void Set_One(int x) {Power_pow(x, MOD - 1);/*a ^ (P-1) = 1 (MOD P)*/;}
inline void Get(int x)
{
Set_One(t2);
Set_Zero(t1);
while (x)
{
if (x & 1) Plus(t1, t1, t2);
Plus(t2, t2, t2);
x >>= 1;
}
}

void Solve()
{
REP(i, 0, N - 1)
{
Set_One(t2);
Copy(fx, t2);
Get(w[i]);
REP(j, 1, n)
{
Plus(t1, t1, j);
Multiply(fx, fx, t1);
Minus(t1, t1, j);
}
Get(w[((-i * m % N) + N) % N]);
Multiply(fx, fx, t1);
Plus(ans, ans, fx);
}
Get(power_pow(N, MOD-2));
Multiply(ans, ans, t1);
Answer(ans);
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×