loj6539。素晴らしいトピック数

問題の意味

順列与える\(\)を求めて、
\ [\ sum_ {I = 1 } ^ n個の\ sum_ {jは= 1} ^ N(i、j)は(a_iを、a_j)を\]

問題の解決策

ハンギングチェーンの足を。
私も料理を感じます
要するに、この最初の出会い馴染み部の主題は馴染みのフォームを形成することが提案、残りは新しい問題です。
(正直に言うと、この問題の残りの部分のために、何の把握本質はまだありませんでした)

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

const int N = 100005, mod = 1e9 + 7;

int n;
int a[N], mu[N], phi[N], cnt[N];
int pr[N];
bool isp[N];
ll ans;
ll f[N];
vector <int> ds[N], st;

void sieve () {
    memset(isp, 1, sizeof isp);
    phi[1] = 1, mu[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (isp[i]) {
            pr[++pr[0]] = i;
            phi[i] = i - 1, mu[i] = -1;
        }
        for (int j = 1; j <= pr[0] && i * pr[j] <= n; ++j) {
            isp[i * pr[j]] = 0;
            if (i % pr[j] == 0) {
                phi[i * pr[j]] = phi[i] * pr[j];
                mu[i * pr[j]] = 0;
                break;
            }
            phi[i * pr[j]] = phi[i] * phi[pr[j]];
            mu[i * pr[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = i; j <= n; j += i) {
            ds[j].push_back(i);
        }
    }
}
int main () {
    scanf("%d", &n), sieve();
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n; ++i) {
        st.clear();
        for (int j = i; j <= n; j += i) {
            for (auto x : ds[a[j]]) {
                ++cnt[x], st.push_back(x);
            }
        }
        for (auto x : st) {
            f[i] += 1ll * phi[x] * cnt[x] % mod * cnt[x];
            f[i] %= mod;
            cnt[x] = 0;
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = i; j <= n; j += i) {
            ans += 1ll * i * mu[j / i] % mod * f[j];
            ans %= mod;
        }
    }
    printf("%lld\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/psimonw/p/11237564.html