1. 程式人生 > >BZOJ3512:DZY Loves Math IV

BZOJ3512:DZY Loves Math IV

傳送門

Sol

好神仙的題目。。
一開始就直接莫比烏斯反演然後就 G G GG
orz 題解
permui

列舉 n n

,就是求 i = 1 n S (
i , m ) \sum_{i=1}^{n}S(i,m)

其中 S (
n , m ) = i = 1 m φ ( n i ) S(n,m)=\sum _{i=1}^m\varphi (ni)

n = i p i c i n=\prod_{i}p_i^{c_i}
y = i = 1 p i c i 1 y=\prod _{i=1} p_i^{c_i-1} w = i = 1 p j w=\prod _{i=1}p_j
那麼
S ( n , m ) = y i = 1 m φ ( w i ) = y i = 1 m φ ( w g c d ( i , w ) ) φ ( i ) g c d ( i , w ) = y i = 1 m φ ( w g c d ( i , w ) ) φ ( i ) e g c d ( i , w ) φ ( e ) = y i = 1 m φ ( i ) e g c d ( i , w ) φ ( w e ) = y i = 1 m φ ( i ) e i , e w φ ( w e ) = y e w φ ( w e ) S ( e , m e ) \begin{aligned} S(n,m)&=y\sum _{i=1}^m\varphi (wi) \\ &=y\sum _{i=1}^m\varphi (\frac{w}{gcd(i,w)})\varphi (i)gcd(i,w) \\ &=y\sum _{i=1}^m\varphi (\frac{w}{gcd(i,w)})\varphi (i)\sum _{e|gcd(i,w)}\varphi (e) \\ &=y\sum _{i=1}^m\varphi (i)\sum _{e|gcd(i,w)}\varphi (\frac{w}{e}) \\ &=y\sum _{i=1}^m\varphi (i)\sum _{e|i,e|w}\varphi (\frac{w}{e}) \\ &=y\sum _{e|w} \varphi (\frac{w}{e})S(e,\lfloor\frac{m}{e}\rfloor) \\ \end{aligned}
運用了 n = d n φ ( d ) n=\sum _{d|n}\varphi (d) 去掉了 g c d gcd

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod(1e9 + 7);
const int maxn(1e6 + 5);
const int blk(80);

inline void Inc(int &x, int y) {
	if ((x += y) >= mod) x -= mod;
}

int pr[maxn], phi[maxn], tot, d, id1[maxn], id2[maxn], idx, m, ans, sphi[maxn], low[maxn];
bitset <maxn> ispr;
map <int, int> s[maxn];

# define ID(x) ((x) <= d ? id1[x] : id2[m / (x)])

int Sumphi(int x) {
    if (x < maxn) return phi[x];
    if (sphi[ID(x)]) return sphi[ID(x)];
    register int ans = (ll)(x + 1) * x / 2 % mod, i, j;
    for (i = 2; i <= x; i = j + 1) j = x / (x / i), Inc(ans, mod - (ll)Sumphi(x / i) * (j - i + 1) % mod);
    return sphi[ID(x)] = ans;
}

int Calc(int n, int v) {
	if (!v || !n) return 0;
	if (n == 1) return Sumphi(v);
	if (v == 1) return (phi[n] - phi[n - 1] + mod) % mod;
	if (s[n].count(v)) return s[n][v];
	register int i, j, ret, y = 1, w = 1, x, cnt, e, dv[30];
	for (cnt = 0, x = n; x > 1; ) {
		w *= low[x], dv[++cnt] = low[x], x /