前 置 知 识 : 前置知识: 前置知识: ∑ i = 1 n ∑ j = 1 n ϕ ( i j ) = ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) \sum_{i=1}^{n}\sum_{j=1}^{n}\phi(ij)=\sum_{i=1}^{n}\sum_{j=1}^{n}\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))} i=1∑nj=1∑nϕ(ij)=i=1∑nj=1∑nϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
证 明 : 证明: 证明:
n = ∏ i = 1 m p i α i n=\prod_{i=1}^{m}p_{i}^{\alpha_{i}} n=i=1∏mpiαi ϕ ( n ) = n ∏ i = 1 m ( 1 − 1 p i ) = n ∏ p ∣ n ( 1 − 1 p ) \phi(n)=n\prod_{i=1}^{m}(1-\frac{1}{p_{i}})=n\prod_{p|n}(1-\frac{1}{p}) ϕ(n)=ni=1∏m(1−pi1)=np∣n∏(1−p1) ϕ ( i ) = i ∏ p 1 ∣ i ( 1 − 1 p 1 ) , ϕ ( j ) = j ∏ p 2 ∣ j ( 1 − 1 p 2 ) \phi(i)=i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}),\phi(j)=j\prod_{p_{2}|j}(1-\frac{1}{p_{2}}) ϕ(i)=ip1∣i∏(1−p11),ϕ(j)=jp2∣j∏(1−p21) ϕ ( i j ) = i j ∏ p ∣ i j ( 1 − 1 p ) = i ∏ p 1 ∣ i ( 1 − 1 p 1 ) × j ∏ p 2 ∣ j ( 1 − 1 p 2 ) ∏ p 3 ∣ i , p 3 ∣ j ( 1 − 1 p 3 ) \phi(ij)=ij\prod_{p|ij}(1-\frac{1}{p})=\frac{i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}) \times j\prod_{p_{2}|j}(1-\frac{1}{p_{2}})}{\prod_{p_{3}|i,p_{3}|j}(1-\frac{1}{p_{3}})} ϕ(ij)=ijp∣ij∏(1−p1)=∏p3∣i,p3∣j(1−p31)i∏p1∣i(1−p11)×j∏p2∣j(1−p21) = i ∏ p 1 ∣ i ( 1 − 1 p 1 ) × j ∏ p 2 ∣ j ( 1 − 1 p 2 ) g c d ( i , j ) ∏ p 3 ∣ g c d ( i , j ) ( 1 − 1 p 3 ) g c d ( i , j ) =\frac{i\prod_{p_{1}|i}(1-\frac{1}{p_{1}}) \times j\prod_{p_{2}|j}(1-\frac{1}{p_{2}})}{gcd(i,j)\prod_{p_{3}|gcd(i,j)}(1-\frac{1}{p_{3}})}gcd(i,j) =gcd(i,j)∏p3∣gcd(i,j)(1−p31)i∏p1∣i(1−p11)×j∏p2∣j(1−p21)gcd(i,j) = ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) =\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))} =ϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
证 完 后 就 可 以 用 上 面 的 公 式 来 推 式 子 了 : 证完后就可以用上面的公式来推式子了: 证完后就可以用上面的公式来推式子了:
∑ i = 1 n ∑ j = 1 n ϕ ( i j ) ϕ ( g c d ( i , j ) ) = ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) g c d ( i , j ) \sum_{i=1}^{n}\sum_{j=1}^{n}\phi(ij)\phi(gcd(i,j))=\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)gcd(i,j) i=1∑nj=1∑nϕ(ij)ϕ(gcd(i,j))=i=1∑nj=1∑nϕ(i)ϕ(j)gcd(i,j)
枚 举 g c d ( i , j ) : 枚举gcd(i,j): 枚举gcd(i,j):
∑ d = 1 n ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) d [ g c d ( i , j ) = = d ] \sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)d[gcd(i,j)==d] d=1∑ni=1∑nj=1∑nϕ(i)ϕ(j)d[gcd(i,j)==d] = ∑ d = 1 n ∑ i = 1 n / d ∑ j = 1 n / d ϕ ( i d ) ϕ ( j d ) d [ g c d ( i , j ) = = 1 ] =\sum_{d=1}^{n}\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)d[gcd(i,j)==1] =d=1∑ni=1∑n/dj=1∑n/dϕ(id)ϕ(jd)d[gcd(i,j)==1] = ∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 n / d ϕ ( i d ) ϕ ( j d ) ∑ x ∣ d μ ( x ) =\sum_{d=1}^{n}d\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)\sum_{x|d}\mu(x) =d=1∑ndi=1∑n/dj=1∑n/dϕ(id)ϕ(jd)x∣d∑μ(x) = ∑ d = 1 n d ∑ x = 1 n / d μ ( x ) ∑ i = 1 n / d x ∑ j = 1 n / d x ϕ ( i d x ) ϕ ( j d x ) =\sum_{d=1}^{n}d\sum_{x=1}^{n/d}\mu(x)\sum_{i=1}^{n/dx}\sum_{j=1}^{n/dx}\phi(idx)\phi(jdx) =d=1∑ndx=1∑n/dμ(x)i=1∑n/dxj=1∑n/dxϕ(idx)ϕ(jdx)
令 T = d x : 令T=dx: 令T=dx:
∑ T = 1 n ∑ d ∣ T d μ ( T d ) ( ∑ i = 1 n / T ϕ ( i T ) ) 2 \sum_{T=1}^{n}\sum_{d|T}d\mu(\frac{T}{d})(\sum_{i=1}^{n/T}\phi(iT))^{2} T=1∑nd∣T∑dμ(dT)(i=1∑n/Tϕ(iT))2
前 面 一 部 分 用 狄 利 克 雷 卷 积 可 以 求 出 来 : μ ∗ i d = ϕ , 于 是 就 可 以 进 一 步 化 简 了 : 前面一部分用狄利克雷卷积可以求出来:\mu*id=\phi,于是就可以进一步化简了: 前面一部分用狄利克雷卷积可以求出来:μ∗id=ϕ,于是就可以进一步化简了:
∑ T = 1 n ϕ ( T ) ( ∑ i = 1 n / T ϕ ( i T ) ) 2 \sum_{T=1}^{n}\phi(T)(\sum_{i=1}^{n/T}\phi(iT))^{2} T=1∑nϕ(T)(i=1∑n/Tϕ(iT))2
令 f ( d , n ) = ∑ i = 1 n / d ϕ ( i d ) , 我 们 发 现 对 于 n ∈ [ i × d , ( i + 1 ) × d ) , ϕ ( d ) × f ( d , n ) 2 的 贡 献 是 相 同 的 , 即 这 一 区 间 都 要 加 上 这 一 贡 献 , 所 以 就 可 以 用 差 分 + 前 缀 和 来 求 了 , 时 间 复 杂 度 大 概 为 O ( n l o g n ) . 令f(d,n)=\sum_{i=1}^{n/d}\phi(id),我们发现对于n\in[i\times d,(i+1)\times d),\phi(d)\times f(d,n)^{2}的贡献是相同的,即这一区间都要加上这一贡献,所以就可以用差分+前缀和来求了,时间复杂度大概为O(nlogn). 令f(d,n)=∑i=1n/dϕ(id),我们发现对于n∈[i×d,(i+1)×d),ϕ(d)×f(d,n)2的贡献是相同的,即这一区间都要加上这一贡献,所以就可以用差分+前缀和来求了,时间复杂度大概为O(nlogn).
#include
using namespace std;
using ll = long long;
const int N = 1e6 + 5, mod = 1e9 + 7;
int n, phi[N], p[N], cnt, ans[N];
bool vis[N];
void get() {
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!vis[i]) {
p[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; p[j] <= n / i; j++) {
vis[i * p[j]] = 1;
if(i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - 1);
}
}
}
int main() {
scanf("%d", &n); get();
for(int i = 1; i <= n; i++) {
ll sum = 0;
for(int j = 1; j * i <= n; j++) {
int x = i * j, y = i * (j + 1);
sum = (sum + phi[x]) % mod;
ll tmp = sum * sum % mod * phi[i] % mod;
ans[x] = (ans[x] + tmp) % mod;
if(y <= n) ans[y] = (ans[y] - tmp + mod) % mod;
}
}
for(int i = 1; i <= n; i++) {
ans[i] = (ans[i] + ans[i - 1]) % mod;
printf("%d\n", ans[i]);
}
return 0;
}