牛客练习赛76 phi and phi 莫比乌斯反演+差分

原题链接:https://ac.nowcoder.com/acm/contest/10845/F

目录

  • 题意
  • 化简
  • Code

题意

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=1nj=1nϕ(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=1nj=1nϕ(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=1ndi=1nj=1nϕ(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=1ndi=1n/dj=1n/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=1ndi=1n/dj=1n/dϕ(id)ϕ(jd)ti,tjμ(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=1ndt=1n/dμ(t)i=1n/tdj=1n/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=1ni=1n/Tϕ(iT)j=1n/Tϕ(jT)dTdμ(dT)

设 F ( n , T ) = ∑ i = 1 n / T ϕ ( i T ) 设F(n, T) = \sum_{i=1}^{n/T}\phi(iT) F(n,T)=i=1n/Tϕ(iT)

= ∑ T = 1 n F ( n , d ) 2 ϕ ( T ) =\sum_{T=1}^{n}F(n,d)^2\phi(T) =T=1nF(n,d)2ϕ(T)

接着就可以直接写了,同样使用差分,考虑F函数对不同n的贡献,把两端点算出来差分一下就可以了

Code

#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();
}

你可能感兴趣的:(数论)