题目大意:给定一个长度为$n$的序列$a_n$,需要求出一个序列$b_n$,满足:
$$
b_k=sumlimits_{i|k}a_i
$$
$nleqslant10^7$
题解:$mathrm{Dirichlet}$前缀和,考虑把$k$写成一个无穷向量$[eta_1,eta_2,eta_3,cdots]$,满足$k=sumlimits_iP_i^{eta_i}$,$P_i$为第$i$个质数。相同的,把$i$写成$[alpha_1,alpha_2,alpha_3,cdots]$,于是:
$$
egin{align*}
b_{eta_{k,1},eta_{k,2},eta_{k,2},cdots}&=sumlimits_{i|k}a_{alpha_{i,1},alpha_{i,2},alpha_{i,3},cdots}\
&=sumlimits_{foralleta_{k,j}geqslantalpha_{i,j}}a_{alpha_{i,1},alpha_{i,2},alpha_{i,3},cdots}
end{align*}
$$
于是先线性筛出质数,再做一个高维前缀和即可。复杂度$O(nloglog n)$
卡点:无
C++ Code:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> const int maxn = 1e7 + 5; typedef unsigned int uint; typedef unsigned long long ull; struct random { ull seed; static const ull multiplier = 0x5deece66dll; static const ull addend = 0xbll; static const ull mask = 0xffffffffffffll; void set_seed (ull _seed) {seed = _seed;} uint next() { seed = (seed * multiplier + addend) & mask; return seed >> 16; } } rnd; int plist[maxn >> 3], ptot; bool notp[maxn]; void sieve(const int n) { for (int i = 2; i <= n; ++i) { if (!notp[i]) plist[ptot++] = i; for (int j = 0, t; (t = i * plist[j]) <= n; ++j) { notp[t] = 1; if (i % plist[j] == 0) break; } } } int n; uint s[maxn]; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n >> rnd.seed; for (int i = 1; i <= n; ++i) s[i] = rnd.next(); sieve(n); for (int i = 0; i < ptot; ++i) { const int P = plist[i]; for (int j = 1, t; (t = j * P) <= n; ++j) s[t] += s[j]; } uint ans = 0; for (int i = 1; i <= n; ++i) ans ^= s[i]; std::cout << ans << ' '; return 0; }