原题链接:https://ac.nowcoder.com/acm/contest/10845/F
a n s ( n ) = ∑ i = 1 n ∑ j = 1 n ϕ ( i j ) ϕ ( g c d ( i , j ) ) ans(n)=\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(ij)\phi(gcd(i,j)) ans(n)=i=1∑nj=1∑nϕ(ij)ϕ(gcd(i,j))
先引入一个定理
ϕ ( i j ) = ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) \phi(ij)=\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i, j))} ϕ(ij)=ϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
然后就变成非常一般的形式
a n s ( n ) = ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) g c d ( i , j ) ans(n)=\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)gcd(i, j) ans(n)=i=1∑nj=1∑nϕ(i)ϕ(j)gcd(i,j)
= ∑ d = 1 n d ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) [ g c d ( i , j ) = d ] =\sum_{d=1}^{n}d\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(i)\phi(j)[gcd(i, j)=d] =d=1∑ndi=1∑nj=1∑nϕ(i)ϕ(j)[gcd(i,j)=d]
= ∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 n / d ϕ ( i d ) ϕ ( j d ) [ g c d ( i , j ) = 1 ] =\sum_{d=1}^{n}d\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)[gcd(i, j)=1] =d=1∑ndi=1∑n/dj=1∑n/dϕ(id)ϕ(jd)[gcd(i,j)=1]
= ∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 n / d ϕ ( i d ) ϕ ( j d ) ∑ t ∣ i , t ∣ j μ ( t ) =\sum_{d=1}^{n}d\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\phi(id)\phi(jd)\sum_{t|i,t|j}\mu(t) =d=1∑ndi=1∑n/dj=1∑n/dϕ(id)ϕ(jd)t∣i,t∣j∑μ(t)
= ∑ d = 1 n d ∑ t = 1 n / d μ ( t ) ∑ i = 1 n / t d ∑ j = 1 n / t d ϕ ( i d t ) ϕ ( j d t ) =\sum_{d=1}^{n}d\sum_{t=1}^{n/d}\mu(t)\sum_{i=1}^{n/td}\sum_{j=1}^{n/td}\phi(idt)\phi(jdt) =d=1∑ndt=1∑n/dμ(t)i=1∑n/tdj=1∑n/tdϕ(idt)ϕ(jdt)
设 T = t d 设T=td 设T=td
= ∑ T = 1 n ∑ i = 1 n / T ϕ ( i T ) ∑ j = 1 n / T ϕ ( j T ) ∑ d ∣ T d μ ( T d ) =\sum_{T=1}^{n}\sum_{i=1}^{n/T}\phi(iT)\sum_{j=1}^{n/T}\phi(jT)\sum_{d|T}d\mu(\frac{T}{d}) =T=1∑ni=1∑n/Tϕ(iT)j=1∑n/Tϕ(jT)d∣T∑dμ(dT)
设 F ( n , T ) = ∑ i = 1 n / T ϕ ( i T ) 设F(n, T) = \sum_{i=1}^{n/T}\phi(iT) 设F(n,T)=i=1∑n/Tϕ(iT)
= ∑ T = 1 n F ( n , d ) 2 ϕ ( T ) =\sum_{T=1}^{n}F(n,d)^2\phi(T) =T=1∑nF(n,d)2ϕ(T)
接着就可以直接写了,同样使用差分,考虑F函数对不同n的贡献,把两端点算出来差分一下就可以了
#include
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 100, M = 5e5 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll prime[N], mu[N], k, ans[N];
ll phi[N];
bool is_prime[N];
inline void init(int n) {
memset(is_prime, true, sizeof is_prime);
mu[1] = 1; phi[1] = 1;
for (int i = 2; i < n; ++i) {
if (is_prime[i]) prime[++k] = i, mu[i] = -1, phi[i] = i-1;
for (int j = 1; j <= k && i * prime[j] < n; ++j) {
is_prime[i * prime[j]] = false;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
} else {
mu[i * prime[j]] = -mu[i];
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
for (int T = 1; T < n; T++) {
ll tmp = 0;
for (int i = T; i < n; i += T) {
int l = i;
int r = min(n, l + T - 1);
tmp = (tmp + phi[i]) % MOD;
ans[l] = (ans[l] + tmp * tmp % MOD * phi[T] % MOD) % MOD;
ans[r + 1] = (ans[r + 1] - tmp * tmp % MOD * phi[T] % MOD + MOD) % MOD;
}
}
for (int i = 1; i < n; i++) ans[i] = ((ans[i] + ans[i-1]) % MOD + MOD) % MOD;
}
void solve() {
init(N);
int n; cin >> n;
for (int i = 1; i <= n; i++) printf("%lld\n", ans[i]);
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}