数学专题 2024.12
数学专题
2024.12
Luogu 3175 按位或
刚开始你有一个数字 \(0\),每一秒钟你会随机选择一个 \([0,2^n-1]\) 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 \(i\) 的概率是 \(p_i\)。保证 \(0\leq p_i \leq 1\),\(\sum p_i=1\) 。问期望多少秒后,你手上的数字变成 \(2^n-1\)。
处理浮点数,\(n \le 20\)。
sol
min-max 容斥。
设 \(U = \{0, 1, 2, \cdots, n-1\}\),\(t(x)\) 为第 \(x\) 个元素被选择的时间。
FWT 即可。
51nod 1355 斐波那契最小公倍数
给定长度为 \(n\) 的序列 \(a_1, a_2, \cdots, a_n\),计算 \(\operatorname{lcm} _{1\le i \le n} fib(a_i)\) 的值。
对 \(10^9+7\) 取模,\(n, a_i \le 10^6\)。
sol
经典性质 \(\gcd(fib(x), fib(y)) = fib(\gcd(x, y))\),证明方法是更相减损术。
设 \(S = \{a_1, a_2, \cdots, a_n\}\),于是:
可以把数看成向量,每一个质数的次数是它的一个分量,gcd 是 min,lcm 是 max,于是可以 min-max 容斥。
对于每个 \(x = \gcd T\),考虑求出 \(fib(x)\) 的次数。
若 \(k = \sum_{i = 1}^n [x \mid a_i]\),这意味着 \(x \mid \gcd T\) 会发生 \(2^k - 1\) 次,其中有 \(2^{k-1}\) 次 \((-1)^{|T|+1}\) 是正的,\(2^{k-1} - 1\) 次是负的。
初始可认为它的指数就是 \(1\),然而还需要减掉 \(x\) 并不是最大公倍数的部分。
f[0] = 0, f[1] = 1;
for (int i = 2; i <= V; ++i) f[i] = fplus(f[i-1], f[i-2]);
int n; read(n);
while (n--) { int x; read(x); c[x] = 1; }
c[1] = 1;
for (int i = 2; i <= V; ++i) {
if (vis[i]) continue;
for (int j = V / i; j > 1; --j) {
vis[i*j] = 1, c[j] |= c[i*j];
}
}
int ans = 1;
for (int i = V; i; --i) {
for (int j = i << 1; j <= V; j += i) c[i] -= c[j];
ans = 1ll * ans * qpow(f[i], mod-1+c[i]) % mod;
}
时间复杂度 \(O(n + V \ln V)\)。
网上现在大部分反演的做法,和这个做法的本质相同,区别主要在于本做法直接考虑每一项的次数。
Luogu 7360 红包
给定 \(n\),\(k\),求:
对 \(998244353\) 取模,\(T\) 组询问,\(1 \le n \le 10^6\),\(1 \le k \le 10^{100}\),\(1 \le T \le 10^3\)。
sol
考虑对 lcm 进行 min-max 容斥。

最后得到的:
考虑预处理 \(f(x) = \prod_{d|x}d^{\mu(x / d)}\) 和它的 “前缀积”,然后显然可以进行整除分块。
性质:\(f(x) \ne 1 \iff x = p^c, p \in \mathrm{Prime}\),且此时 \(f(x) = p\)。
从右推左显然,考虑由左边证明右边,即 \(x\) 的不同质因子个数不是 \(1\) 时 \(f(x) = 1\)。
\(x = 1\) 时平凡。
假设一共有 \(m > 1\) 个不同质因子,选择了 \(k\) 个质因子各一次时,根据 \(\mu(x)\) 的定义,有 \(\mu(cur) = (-1)^k\)。
\(p\) 的总幂次:
注意 \(k\) 读入时需要使用 exEuler 处理。
QOJ 5376 xor
求:
对 \(998244353\) 取模,\(0 \le n < 2^{30}\),\(d \le 10^5\)。
sol
拉格朗日插值可以用 \(O(d \log V)\) 预处理 \(O(d)\) 在线求出 \(\sum_{i=1}^n i^d\)。(log 是费马小定理。)
设当前位为 \(x\)(\(0 \le x \le 30\))。
当前需要考虑计算的情况是:
当前位为 \(1\),三个数更高的位都卡住上界,当前位一部分为 \(0\),不全为 \(1\),所能构成的答案。
设 \(low\) 比 \(x\) 低的位,\(high\) 为比 \(x\) 高的位。
low = A&((1<<x)-1),high = A>>(x+1)<<(x+1)。
三个数,其中一个选 \(0\) 将另外两个数 xor 出的结果变成 \([high + t 2^x, high + t2^x + (2^x-1)]\),其中 \(t \in \{0, 1\}\),且与 \(1\) 的个数有关。
不难发现那个选 \(0\) 的数的每一种不同取值,都能对应区间内一种取值(一一对应)。
设 \(res_0\) 为 \(t = 0\) 时的区间 \(d\) 次方和,\(res_1\) 为 \(t = 1\) 时的。
所以,对于当前位:
全 \(0\):\(4^x \times res_0\);
\(1\) 个 \(1\):\(3 \times 2^x \times low \times res_1\);
\(2\) 个 \(1\):\(3 \times low \times low \times res_0\)。
枚举累加即可。
关于拉格朗日插值:
而中国剩余定理(设 \(m = \prod p_i\)):
式子长得非常像,因为:
本质就是一个凑。
校内水题。
公约数
给定 \(n, m, l\),计算:
对 \(10^9+7\) 取模,多测,\(T \le 10^3\),\(1 \le n, m, l \le 2 \times 10^7\)。
sol
假设 \(i, j, k\) 中 \(p\) 的次数分别为 \(a, b, c\),钦定 \(a \le b \le c\),则:
\(\min(a + b, b + c, c + a) + \min(a, b, c) = 2a + b\),
\(\min(a, b) + min(b, c) + min(c, a) = 2a + b\)。
于是 \(\gcd(ij, jk, ki) \times \gcd(i, j, k) = \gcd(i, j) \times gcd(j, k) \times gcd(k, i)\),约掉。
所求即:
三部分独立,分别算。于是转化成经典问题 \(\sum_{i=1}^n \sum_{j=1}^m {\gcd}^2(i, j)\)。
式子很好推就不再写了。
化简之后会出现迪利克雷卷积:\(f = id^2 * \mu\)。
线性筛 + 数论分块板子,预处理 \(f(x) = \sum_{d \mid x} d^2\mu(x/d)\) 即可。
莫比乌斯
定义函数 \(f: \mathbb N \rightarrow \mathbb N\):
\(f(0) = f(1) = 1\),\(\forall i > 1\),\(f(i) = xf(i-1) + yf(i-2)\)。
给定 \(A = \prod_{0 \le i < n} p_i^{c_i}\),求:
对 \(10^9+7\) 取模,\(1 \le n \le 20\),\(1 \le p_i, c_i, x, y \le 10^9\)。
sol
注意到含平方因子时没有贡献,\(s\) 只能是若干个质数相乘。
设全集 \(U = \{0, 1, 2, \cdots n-1\}\),\(S, T \subseteq U\),分别表示 \(s, t\) 所选择的质数编号。
设 \(cnt(S)\) 为 \(s = \prod_{i \in S}p^i\) 时合法的 \(k\) 数量,显然:\(cnt(S) = \prod_{0 \le i < n} (c_i + [i \notin S])\)。
FWT 即可。
// 快读、qmod、mat 部分略
const int N = 20;
int n, p[N], c[N];
mat f1[N], f[1<<N];
int ctz[1<<N], ppc[1<<N];
int val[1<<N];
void fwt() {
for (int len = 1; len < 1<<n; len <<= 1) {
for (int i = 0; i < 1<<n; i += len<<1) {
for (int j = i; j < i + len; ++j) {
Fplus(val[j+len], val[j]);
}
}
}
}
int solve(mat ori) {
int ans = 0;
// mat ori; //
f[0] = ori;
// for (int i = 0; i < n; ++i) f1[i] = qpow(ori, p[i]);
for (int i = 1; i < 1<<n; ++i) {
ctz[i] = (i & 1) ? 0 : ctz[i>>1] + 1;
ppc[i] = ppc[i>>1] + (i & 1);
f[i] = qpow(f[i^(i&-i)], p[ctz[i]]);
}
for (int i = 0; i < 1<<n; ++i) {
val[i] = fplus(f[i](0, 0), f[i](1, 0));
if (ppc[i] & 1) val[i] = mod - val[i];
}
fwt();
for (int i = 0; i < 1<<n; ++i) {
int cnt = 1;
for (int x = 0; x < n; ++x) {
if (i >> x & 1) cnt = 1ll * cnt * c[x] % mod;
else cnt = 1ll * cnt * (c[x] + 1) % mod;
}
(ppc[i] & 1 ? Fminus : Fplus)(ans, 1ll * cnt * val[i] % mod);
}
return ans;
}
int main() {
int x, y;
read(n), read(x), read(y);
mat ori;
ori(0, 0) = 0, ori(0, 1) = y, ori(1, 0) = 1, ori(1, 1) = x;
for (int i = 0; i < n; ++i) read(p[i]), read(c[i]);
printf("%d\n", solve(ori));
return 0;
}

浙公网安备 33010602011771号