数学专题 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\) 个元素被选择的时间。

\[E( \max_{x \in U} t(x)) = \sum_{S \subseteq U} (-1)^{|S| + 1} E(\min_{x \in S} t(x)) \]

\[E(\min_{x \in S} t(x)) = \frac{1}{\sum_{T \cap S \neq \varnothing} p_T} = \frac{1}{1 - \sum_{T \subseteq \overline S}} \]

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 容斥。

\[\operatorname{lcm}_{x \in S} \{fib(x)\} =\prod_{T \in S, T \ne \varnothing}(\gcd_{x \in T}\{fib(x)\})^{(-1)^{|T| + 1}} =\prod_{T \in S, T \ne \varnothing}fib\left(\gcd T\right)^{(-1)^{|T| + 1}} \]

对于每个 \(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\),求:

\[\prod_{\forall 1 \le i \le k, 1 \le A_i \le n} \operatorname{lcm}_{i=1}^k \{A_i\} \]

\(998244353\) 取模,\(T\) 组询问,\(1 \le n \le 10^6\)\(1 \le k \le 10^{100}\)\(1 \le T \le 10^3\)

sol

考虑对 lcm 进行 min-max 容斥。

这里的 LaTeX gugu 了

最后得到的:

\[\prod_{T=1}^n(\prod_{d|T}d^{\mu(T/d)})^{n^k-(n-\lfloor n/T \rfloor)^k} \]

考虑预处理 \(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\) 的总幂次:

\[c + c\sum_{i=1}^m(-1)^i\binom {m-1}{i}+ (c-1)\sum_{i=1}^{m}(-1)^i\binom {m-1}{i-1}\\ =c\sum_{i=0}^m(-1)^i\binom mi + \sum_{i=0}^{m-1}(-1)^i \binom {m-1}i = 0 + 0 = 0 \]

注意 \(k\) 读入时需要使用 exEuler 处理。

QOJ 5376 xor

求:

\[\sum_{0 \le x, y, z < n} (x \oplus y \oplus z)^d \]

\(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\)

枚举累加即可。

关于拉格朗日插值:

\[\sum_{0 \le i \le n} \prod_{0 \le j \le n, j \ne i} \frac{x-j}{i-j}f(i) \]

而中国剩余定理(设 \(m = \prod p_i\)):

\[\left(\sum_{1 \le i \le n} \frac m{p_i} \times inv_{p_i}(\frac m{p_i}) \times a_i \right) \bmod m \]

式子长得非常像,因为:

本质就是一个凑。


校内水题。

公约数

给定 \(n, m, l\),计算:

\[\sum_{i=1}^{n}\sum_{j=1}^m\sum_{k=1}^{l} \gcd(ij, jk, ki) \times \gcd(i, j, k) \times \frac{\gcd^2(i,j) + \gcd^2(j, k) + \gcd^2(k, i)}{\gcd(i, j) \times \gcd(j, k) \times \gcd(k, i)}\]

\(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\sum_{k=1}^{l} {\gcd}^2(i,j) + {\gcd}^2(j, k) + {\gcd}^2(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}\),求:

\[\sum_{k \mid A} \sum_{s \mid k} \mu(s)\sum_{t \mid s}\mu(t)f(t) \]

\(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])\)

\[\sum_{S \subseteq U} cnt(S)(-1)^{|S|}\sum_{T \subseteq S} f(T)(-1)^{|T|} \]

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;
}
posted @ 2024-12-29 18:48  SZwinsun  阅读(51)  评论(0)    收藏  举报