我是靠谱客的博主 怕孤单蜡烛,最近开发中收集的这篇文章主要介绍莫比乌斯反演例题集---(自用)参考:大佬1 大佬2 大佬3 大佬4,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

参考:大佬1 大佬2 大佬3 大佬4

P3455 [POI2007]ZAP-Queries

求 解 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] 求解sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k] i=1nj=1m[gcd(i,j)=k]
反 演 过 程 : 反演过程:
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k] i=1nj=1m[gcd(i,j)=k]

∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ε [ g c d ( i , j ) = 1 ] sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{m}{k} right rfloor}varepsilon[gcd(i,j)=1] i=1knj=1kmε[gcd(i,j)=1]

枚 举 d : 枚举d: d

∑ d = 1 ⌊ m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) ⌋ μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ sum_{d=1}^{left lfloor min(left lfloor frac{n}{k} right rfloor,left lfloor frac{m}{k} right rfloor)right rfloor}mu(d)left lfloor frac{n}{kd} right rfloor left lfloor frac{m}{kd} right rfloor d=1min(kn,km)μ(d)kdnkdm

先 预 处 理 μ , 然 后 整 数 分 块 做 , 复 杂 度 为 O ( n + T n ) red{先预处理mu,然后整数分块做,复杂度为O(n + Tsqrt n)} μO(n+Tn )

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 5e5 + 10;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;

ll sum[N]; // 记录莫比乌斯函数前缀和


void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }

    for(int i = 1;i < N; i++) {
        sum[i] = sum[i - 1] + mu[i];
    }
}

ll k;

ll Ans(ll n, ll m) {
    ll ans = 0;
    n /= k, m /= k;
    int mx = min(n, m);
    for(int l = 1, r;l <= mx; l = r + 1) {
        r = min(n / (n / l), m / (m / l));
        ans += (n / l) * (m / l) * (sum[r] - sum[l - 1]);
    }
    return ans;
}

void solve() {
    Mobi();
    int T;
    cin >> T;
    while(T--) {
        ll n, m;
        cin >> n >> m >> k;
        cout << Ans(n, m) << endl;
    }
}


signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P2257 YY的GCD

求 解 ∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] 求解sum_{pin prime}sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=p] pprimei=1nj=1m[gcd(i,j)=p]
反 演 过 程 和 上 面 几 乎 一 样 , 就 多 了 一 维 p 为 质 数 的 情 况 , 直 接 化 简 为 : 反演过程和上面几乎一样,就多了一维p为质数的情况,直接化简为: p

∑ p ∈ p r i m e ∑ d = 1 ⌊ m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ⌋ μ ( d ) ⌊ n p d ⌋ ⌊ m p d ⌋ sum_{pin prime}sum_{d=1}^{left lfloor min(left lfloor frac{n}{p} right rfloor,left lfloor frac{m}{p} right rfloor)right rfloor}mu(d)left lfloor frac{n}{pd} right rfloor left lfloor frac{m}{pd} right rfloor pprimed=1min(pn,pm)μ(d)pdnpdm

这 里 的 复 杂 度 为 O ( n + T n n ) , 但 明 显 不 够 , 所 以 需 要 继 续 化 简 , 这 里 的 优 化 可 以 用 T 替 换 p d , 则 d = T p , 替 换 后 的 式 子 为 : 这里的复杂度为O(n+Tsqrt n sqrt n),但明显不够,所以需要继续化简,这里的优化可以用T替换pd,则d=frac{T}{p},替换后的式子为: O(n+Tn n )Tpdd=pT

∑ T = 1 m i n ( n , m ) ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ p ∣ T    p ∈ p r i m e μ ( T p ) sum_{T=1}^{min(n,m)})left lfloor frac{n}{T} right rfloor left lfloor frac{m}{T} right rfloorsum_{p|T;pin prime}mu(frac{T}{p}) T=1min(n,m))TnTmpTpprimeμ(pT)

令 F ( x ) = ∑ p ∣ x    p ∈ p r i m e μ ( x p ) 令blue{F(x)=sum_{p|x;pin prime}mu(frac{x}{p})} F(x)=pxpprimeμ(px)

得 : 得:

∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ F ( T ) sum_{pin prime}sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=p]=sum_{T=1}^{min(n,m)}left lfloor frac{n}{T} right rfloor left lfloor frac{m}{T} right rfloor F(T) pprimei=1nj=1m[gcd(i,j)=p]=T=1min(n,m)TnTmF(T)

O ( n ) 处 理 μ , O ( n l o g n ) 处 理 F , O ( n ) 询 问 分 块 , 即 复 杂 度 为 O ( n l o g n + T n ) red{O(n)处理mu,O(nlogn)处理F,O(sqrt n)询问分块,即复杂度为O(nlogn + Tsqrt n)} O(n)μO(nlogn)FO(n )O(nlogn+Tn )

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 1e7 + 10;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;

ll sum[N]; // 记录莫比乌斯函数前缀和
ll F[N];


void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }

    for(int i = 1;i <= cnt; i++) {
        for(int j = 1;j * prime[i] < N; j++) {
            F[j * prime[i]] += mu[j];
        }
    }

    for(int i = 1;i < N; i++) {
        F[i] += F[i - 1];
    }
}

ll k;

ll Ans(ll N, ll M) {
    ll ans = 0;
    ll n = N, m = M;
    int mx = min(n, m);
    for (int l = 1, r; l <= mx; l = r + 1) {
        r = min(n / (n / l), m / (m / l));
        ans += (n / l) * (m / l) * (F[r] - F[l - 1]);
    }
    return ans;
}

void solve() {
    Mobi();
    int T;
    cin >> T;
    while(T--) {
        ll n, m;
        cin >> n >> m;
        cout << Ans(n, m) << endl;
    }
}


signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P1390 公约数的和

求 解 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) 求解sum_{i=1}^nsum_{j=i+1}^ngcd(i,j) i=1nj=i+1ngcd(i,j)

先 来 看 看 基 本 形 式 : 先来看看基本形式:
∑ i = 1 n ∑ j = 1 n g c d ( i , j ) sum_{i=1}^nsum_{j=1}^ngcd(i,j) i=1nj=1ngcd(i,j)
则 a n s = C a l c ( n , n ) − n ( n + 1 ) 2 2 , 首 先 减 去 g c d ( i , i ) 的 个 数 n ( n + 1 ) 2 , 然 后 减 去 g c d ( i , j ) = g c d ( j , i ) 的 个 数 , 直 接 除 2 即 可 , 则 : 则blue{ans=frac{Calc(n,n)-frac{n(n+1)}{2}}{2}},首先减去gcd(i,i)的个数frac{n(n+1)}{2},然后减去gcd(i,j)=gcd(j,i)的个数,直接除2即可,则: ans=2Calc(n,n)2n(n+1)gcd(i,i)2n(n+1)gcd(i,j)=gcd(j,i)2
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n k [ g c d ( i , j ) = k ] sum_{i=1}^nsum_{j=1}^nsum_{k=1}^nk[gcd(i,j)=k] i=1nj=1nk=1nk[gcd(i,j)=k]

枚 举 k : 枚举k: k

∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = ⌊ i + 1 k ⌋ ⌊ n k ⌋ [ g c d ( i , j ) = 1 ] sum_{k=1}^nksum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=left lfloor frac{i+1}{k} right rfloor}^{left lfloor frac{n}{k} right rfloor}[gcd(i,j)=1] k=1nki=1knj=ki+1kn[gcd(i,j)=1]

∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ∑ d ∣ i    d ∣ j μ ( d ) sum_{k=1}^nksum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}sum_{d|i;d|j}mu(d) k=1nki=1knj=1kndidjμ(d)

∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ 1 sum_{k=1}^nksum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}sum_{j=1}^{left lfloor frac{n}{kd} right rfloor}1 k=1nkd=1knμ(d)i=1kdnj=1kdn1

∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 sum_{k=1}^nksum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)(left lfloor frac{n}{kd} right rfloor)^2 k=1nkd=1knμ(d)(kdn)2

令 T = k d 并 枚 举 T , 得 : 令blue{T=kd并枚举T},得: T=kdT

∑ T = 1 n ∑ d ∣ T μ ( d ) T d ( ⌊ n T ⌋ ) 2 sum_{T=1}^nsum_{d|T}mu(d)frac{T}{d}(left lfloor frac{n}{T} right rfloor)^2 T=1ndTμ(d)dT(Tn)2

中 间 部 分 有 ∑ d ∣ T μ ( d ) T d = φ ( T ) , 因 为 φ = μ ∗ i d , 即 得 : 中间部分有blue{sum_{d|T}mu(d)frac{T}{d}=varphi (T),因为varphi =mu * id},即得: dTμ(d)dT=φ(T)φ=μid

∑ T = 1 n φ ( T ) ( ⌊ n T ⌋ ) 2 sum_{T=1}^nvarphi (T)(left lfloor frac{n}{T} right rfloor)^2 T=1nφ(T)(Tn)2

则 最 终 答 案 为 : 则最终答案为:

a n s = ∑ T = 1 n φ ( T ) ( ⌊ n T ⌋ ) 2 − n ( n + 1 ) 2 2 red{ans=frac{sum_{T=1}^nvarphi (T)(left lfloor frac{n}{T} right rfloor)^2-frac{n(n+1)}{2}}{2}} ans=2T=1nφ(T)(Tn)22n(n+1)

O ( n ) 预 处 理 φ , n 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n + n ) red{O(n)预处理varphi,sqrt n询问分块,总时间复杂度为O(n+sqrt n)} O(n)φn O(n+n )

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const ll P = 1e9 + 7;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 2e6 + 10;

int phi[N];
bool is_prime[N];
int prime[N];
int tot;

ll f[N];

void Euler()
{
    phi[1] = 1;
    is_prime[1] = true;
    for(int i = 2;i < N; i++){
        if(!is_prime[i]) {
            phi[i] = i - 1;
            prime[++tot] = i;
        }
        for(int j = 1;j <= tot && i * prime[j] < N; j++){
            is_prime[i * prime[j]] = true;
            if(i % prime[j]) {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
            else{
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
        }
    }

    for(int i = 1;i < N; i++) {
        f[i] = f[i - 1] + phi[i];
    }
}

ll Calc(ll n) {
    ll ans = 0;

    for(ll l = 1, r;l <= n;l = r + 1) {
        r = min(n, n / (n / l));
        ans += (f[r] - f[l - 1]) * (n / l) * (n / l);
    }
    return ans;
}

void solve() {
    Euler();
    ll n;
    cin >> n;
    cout << (Calc(n) - n * (n + 1) / 2) / 2 << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P1829 [国家集训队]Crash的数字表格 / JZPTAB

求 解 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) 求解sum_{i=1}^nsum_{j=1}^mlcm (i,j) i=1nj=1mlcm(i,j)

由 g c d 和 l c m 之 间 的 关 系 得 : 由gcd和lcm之间的关系得: gcdlcm

∑ i = 1 n ∑ j = 1 m i j g c d ( i , j ) sum_{i=1}^nsum_{j=1}^mfrac{ij}{gcd(i,j)} i=1nj=1mgcd(i,j)ij

∑ k = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m i j k [ g c d ( i , j ) = k ] sum_{k=1}^{min(n,m)}sum_{i=1}^nsum_{j=1}^mfrac{ij}{k}[gcd(i,j)=k] k=1min(n,m)i=1nj=1mkij[gcd(i,j)=k]

∑ k = 1 m i n ( n , m ) ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ i j k 2 k [ g c d ( i , j ) = 1 ] sum_{k=1}^{min(n,m)}sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{m}{k} right rfloor}frac{ijk^2}{k}[gcd(i,j)=1] k=1min(n,m)i=1knj=1kmkijk2[gcd(i,j)=1]

∑ k = 1 m i n ( n , m ) k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ i j ∑ d ∣ i    d ∣ j μ ( d ) sum_{k=1}^{min(n,m)}ksum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{m}{k} right rfloor}ijsum_{d|i;d|j}mu(d) k=1min(n,m)ki=1knj=1kmijdidjμ(d)

枚 举 d 得 : 枚举d得: d

∑ k = 1 m i n ( n , m ) k ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ∑ i = 1 ⌊ n k d ⌋ i d ∑ j = 1 ⌊ m k d ⌋ j d sum_{k=1}^{min(n,m)}ksum_{d=1}^{min(left lfloor frac{n}{k} right rfloor,left lfloor frac{m}{k} right rfloor)}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}idsum_{j=1}^{left lfloor frac{m}{kd} right rfloor}jd k=1min(n,m)kd=1min(kn,km)μ(d)i=1kdnidj=1kdmjd

∑ k = 1 m i n ( n , m ) k ∑ d = 1 m i n ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) d 2 ∑ i = 1 ⌊ n k d ⌋ i ∑ j = 1 ⌊ m k d ⌋ j sum_{k=1}^{min(n,m)}ksum_{d=1}^{min(left lfloor frac{n}{k} right rfloor,left lfloor frac{m}{k} right rfloor)}mu(d)d^2sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}isum_{j=1}^{left lfloor frac{m}{kd} right rfloor}j k=1min(n,m)kd=1min(kn,km)μ(d)d2i=1kdnij=1kdmj

令 f ( x ) = ∑ i = 1 x i , F ( n , m ) = ∑ d = 1 m i n ( n , m ) μ ( d ) d 2 f ( n d ) f ( m d ) , 得 : 令blue{f(x)=sum_{i=1}^{x}i,F(n,m)=sum_{d=1}^{min(n,m)}mu(d)d^2f(frac{n}{d})f(frac{m}{d})},得: f(x)=i=1xiF(n,m)=d=1min(n,m)μ(d)d2f(dn)f(dm)

∑ k = 1 m i n ( n , m ) k F ( ⌊ n k ⌋ , ⌊ m k ⌋ ) sum_{k=1}^{min(n,m)}kF(left lfloorfrac{n}{k}right rfloor,left lfloorfrac{m}{k}right rfloor) k=1min(n,m)kF(kn,km)

O ( n ) 处 理 μ , O ( 1 ) 处 理 f ( 等 差 数 列 , 在 计 算 F 的 过 程 中 直 接 直 接 计 算 ) , O ( n ) 分 块 询 问 F , 答 案 分 块 询 问 O ( n ) , 总 复 杂 度 为 O ( n + n 3 4 ) red{O(n)处理mu,O(1)处理f(等差数列,在计算F的过程中直接直接计算),O(sqrt {sqrt n})分块询问F,答案分块询问O(sqrt n),总复杂度为O(n+n^{frac{3}{4}})} O(n)μ,O(1)fFO(n )FO(n )O(n+n43)

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 1e7 + 10;

const ll mod = 20101009;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;

ll sum[N];

void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }

    for(int i = 1;i < N; i++) {
        sum[i] = (sum[i - 1] + mu[i] * i % mod * i % mod) % mod;
    }
}

ll Ans(ll n, ll m)
{
    ll inv2 = (mod + 1) / 2;
    ll ans = 0;
    ll p = min(n, m);
    for(int k = 1;k <= p; k++) {
        int x = n / k, y = m / k, P = min(x, y);
        ll Sum = 0;
        for(int l = 1, r;l <= P; l = r + 1) {
            r = min(x / (x / l), (y / (y / l)));
            Sum = (Sum + (sum[r] - sum[l - 1] + mod) % mod * (1 + x / l) % mod * (x / l) % mod * inv2 % mod * (1 + y / l) % mod * (y / l) % mod * inv2 % mod) % mod;
        }
        ans = (ans + Sum * k % mod) % mod;
    }
    return ans;
}

void solve() {
    Mobi();
    ll n, m;
    cin >> n >> m;
    cout << Ans(n, m) << endl;

}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P3768 简单的数学题

求 解 ∑ i = 1 n ∑ j = 1 n i j ( g c d ( i , j ) )    m o d    p 求解sum_{i=1}^nsum_{j=1}^nij(gcd(i,j));mod ;p i=1nj=1nij(gcd(i,j))modp
∑ k = 1 n ∑ i = 1 n ∑ j = 1 n i j k [ g c d ( i , j ) = k ] sum_{k=1}^nsum_{i=1}^nsum_{j=1}^nijk[gcd(i,j)=k] k=1ni=1nj=1nijk[gcd(i,j)=k]

∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ i j k 2 [ g c d ( i , j ) = 1 ] sum_{k=1}^nksum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}ijk^2[gcd(i,j)=1] k=1nki=1knj=1knijk2[gcd(i,j)=1]

∑ k = 1 n k 3 ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ i j ∑ d ∣ i    d ∣ j μ ( d ) sum_{k=1}^nk^3sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}ijsum_{d|i;d|j}mu(d) k=1nk3i=1knj=1knijdidjμ(d)

∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ i d ∑ j = 1 ⌊ n k d ⌋ j d sum_{k=1}^nk^3sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}idsum_{j=1}^{left lfloor frac{n}{kd} right rfloor}jd k=1nk3d=1knμ(d)i=1kdnidj=1kdnjd

∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d 2 ∑ i = 1 ⌊ n k d ⌋ i ∑ j = 1 ⌊ n k d ⌋ j sum_{k=1}^nk^3sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)d^2sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}isum_{j=1}^{left lfloor frac{n}{kd} right rfloor}j k=1nk3d=1knμ(d)d2i=1kdnij=1kdnj

令 f ( x ) = ∑ i = 1 x i , 则 式 子 变 为 : 令blue{f(x)=sum_{i=1}^xi},则式子变为: f(x)=i=1xi

∑ k = 1 n k 3 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d 2 f 2 ( n k d ) sum_{k=1}^nk^3sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)d^2f^2(frac{n}{kd}) k=1nk3d=1knμ(d)d2f2(kdn)

到 这 里 , 时 间 复 杂 度 为 O ( n + n n ) , 我 没 尝 试 过 , 但 是 还 可 以 继 续 化 简 , 化 简 方 法 有 替 换 , 用 T 替 换 k d , 则 : 到这里,时间复杂度为O(n+nsqrt n),我没尝试过,但是还可以继续化简,化简方法有替换,用T替换kd,则: O(n+nn )Tkd

∑ T = 1 n f 2 ( n T ) T 2 ∑ k ∣ T k ∗ μ ( T k ) sum_{T=1}^nf^2(frac{n}{T})T^2sum_{k|T}k*mu(frac{T}{k}) T=1nf2(Tn)T2kTkμ(kT)

∑ T = 1 n f 2 ( n T ) T 2 ( i d ∗ μ ) T sum_{T=1}^nf^2(frac{n}{T})T^2red{(id*mu)T} T=1nf2(Tn)T2(idμ)T

∑ T = 1 n f 2 ( n T ) T 2 φ ( T ) sum_{T=1}^nf^2(frac{n}{T})T^2red{varphi (T)} T=1nf2(Tn)T2φ(T)

可 以 杜 教 筛 筛 T 2 φ ( T ) 的 前 缀 和 , 因 为 n 最 高 有 1 0 10 , 明 显 数 组 存 不 下 , 所 以 对 于 5 e 6 可 以 用 数 组 直 接 过 度 求 前 缀 和 , 对 于 后 面 就 可 以 用 杜 教 筛 求 前 缀 和 , 然 后 用 m a p 存 下 ( S T L 的 好 处 ) , 过 程 如 下 : blue{可以杜教筛筛T^2varphi (T)的前缀和,因为n最高有10^{10},明显数组存不下,所以对于5e6可以用数组直接过度求前缀和,对于后面就可以用杜教筛求前缀和,然后用map存下(STL的好处),过程如下:} T2φ(T)n10105e6mapSTL

参 考 : 参考: 杜教筛

先 看 杜 教 筛 的 基 本 形 式 ( 与 上 面 无 关 ) : 设 S ( n ) = ∑ i = 1 n f ( i ) , 定 义 一 个 新 函 数 为 g , 则 有 先看杜教筛的基本形式(与上面无关):设S(n)=sum_{i=1}^{n}f(i),定义一个新函数为g,则有 ()S(n)=i=1nf(i)g

∑ i = 1 n ( f ∗ g ) i sum_{i=1}^n(f*g)i i=1n(fg)i

∑ i = 1 n ∑ x y = i f ( x ) g ( y ) sum_{i=1}^nsum_{xy=i}f(x)g(y) i=1nxy=if(x)g(y)

∑ y = 1 n g ( y ) ∑ x y ≤ n f ( x ) sum_{y=1}^ng(y)sum_{xyleq n}f(x) y=1ng(y)xynf(x)

∑ y = 1 n g ( y ) ∑ x = 1 ⌊ n y ⌋ f ( x ) sum_{y=1}^ng(y)sum_{x=1}^{left lfloor frac{n}{y} right rfloor}f(x) y=1ng(y)x=1ynf(x)

∑ y = 1 n g ( y ) S ( ⌊ n y ⌋ ) sum_{y=1}^ng(y)S(left lfloor frac{n}{y} right rfloor) y=1ng(y)S(yn)

则 有 : 则有:

∑ i = 1 n ( f ∗ g ) i = g ( 1 ) S ( n ) + ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) sum_{i=1}^n(f*g)i=g(1)S(n)+sum_{y=2}^ng(y)S(left lfloor frac{n}{y} right rfloor) i=1n(fg)i=g(1)S(n)+y=2ng(y)S(yn)

S ( n ) = ∑ i = 1 n ( f ∗ g ) i − ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) g ( 1 ) red{S(n)=frac{sum_{i=1}^n(f*g)i-sum_{y=2}^ng(y)S(left lfloor frac{n}{y} right rfloor)}{g(1)}} S(n)=g(1)i=1n(fg)iy=2ng(y)S(yn)

对 于 本 题 , 要 找 到 合 适 的 g 函 数 , 因 为 我 们 求 的 前 缀 和 为 S ( n ) = ∑ i = 1 n i 2 φ ( i ) , f ( i ) = i 2 φ ( i ) , 所 以 设 g ( n ) = n 2 。 对于本题,要找到合适的g函数,因为我们求的前缀和为S(n)=sum_{i=1}^ni^2varphi(i),f(i)=i^2varphi(i),所以设g(n)=n^2。 gS(n)=i=1ni2φ(i),f(i)=i2φ(i)g(n)=n2

∑ i = 1 n g ( i ) = x ( x + 1 ) ( 2 x + 1 ) 6 sum_{i=1}^ng(i)=frac{x(x+1)(2x+1)}{6} i=1ng(i)=6x(x+1)(2x+1)

( f ∗ g ) x = ∑ d ∣ x f ( d ) g ( x d ) = ∑ d ∣ x d 2 φ ( d ) x 2 d 2 = x 2 ∑ d ∣ x φ ( d ) = x 2 i d ( x ) = x 3 (f*g)x=sum_{d|x}f(d)g(frac{x}{d})=sum_{d|x}d^2varphi(d)frac{x^2}{d^2}=x^2sum_{d|x}varphi(d)=x^2id(x)=x^3 (fg)x=dxf(d)g(dx)=dxd2φ(d)d2x2=x2dxφ(d)=x2id(x)=x3

∑ i = 1 n ( f ∗ g ) i = ∑ i = 1 n i 3 = x 2 ( x + 1 ) 2 4 sum_{i=1}^n(f*g)i=sum_{i=1}^ni^3=frac{x^2(x+1)^2}{4} i=1n(fg)i=i=1ni3=4x2(x+1)2

S ( n ) = n 2 ( n + 1 ) 2 4 − ∑ y = 2 n g ( y ) S ( ⌊ n y ⌋ ) red{S(n)=frac{n^2(n+1)^2}{4}-sum_{y=2}^ng(y)S(left lfloor frac{n}{y} right rfloor)} S(n)=4n2(n+1)2y=2ng(y)S(yn)

O ( n 2 3 ) 处 理 T 2 φ ( T ) 的 前 缀 和 , f 可 以 O ( 1 ) 算 出 , O ( n ) 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n 2 3 ) red{O(n^{frac{2}{3}})处理T^2varphi (T)的前缀和,f可以O(1)算出,O(sqrt n) 询问分块,总时间复杂度为O(n^frac{2}{3})} O(n32)T2φ(T)fO(1)O(n )O(n32)

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 5e6 + 10;

ll n, mod, inv4, inv6;
ll phi[N];
bool is_prime[N];
int prime[N];
int tot;

ll sum[N];

void Get_phi() {
    phi[1] = 1;
    is_prime[1] = true;
    for(int i = 2;i <= N; i++){
        if(!is_prime[i]) {
            phi[i] = i - 1;
            prime[++tot] = i;
        }
        for(int j = 1;j <= tot && i * prime[j] < N; j++){
            is_prime[i * prime[j]] = true;
            if(i % prime[j]) {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
            else{
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
        }
    }
    for(int i = 1;i < N; i++) {
        sum[i] = (sum[i - 1] + (ll)phi[i] * i % mod * i % mod) % mod;
    }
}

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b){
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

ll sum1(ll x) {x %= mod; return (1 + x) % mod * x % mod * (1 + x) % mod * x % mod * inv4 % mod;}
ll sum2(ll x) {x %= mod; return x % mod * (1 + x) % mod * (2 * x + 1) % mod * inv6 % mod;}

map<ll, ll> mp;

ll Calc(ll x) {
    if(x < N) return sum[x];
    if(mp[x]) return mp[x];
    ll num = sum1(x);
    for(ll l = 2, r;l <= x;l = r + 1) {
        r = x / (x / l);
        num = (num - Calc(x / l) % mod * (sum2(r) - sum2(l - 1) + mod) % mod + mod) % mod;
    }
    return mp[x] = num;
}

ll Ans() {
    ll ans = 0;
    for(ll l = 1, r;l <= n; l = r + 1) {
        r = n / (n / l);
        ans = (ans + sum1(n / l) % mod * (Calc(r) - Calc(l - 1) % mod + mod) % mod) % mod;
    }
    return ans;
}

void solve() {
    cin >> mod >> n;
    Get_phi();
    inv4 = quick_pow(4, mod - 2);
    inv6 = quick_pow(6, mod - 2);
    cout << Ans() << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P3327 [SDOI2015]约数个数和

求 解 ∑ i = 1 n ∑ j = 1 m d ( i j ) 求解sum_{i=1}^nsum_{j=1}^md (ij) i=1nj=1md(ij)

约 数 的 重 要 性 质 : ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] red{约数的重要性质:(ij)=sum_{x|i}sum_{y|j}[gcd(x,y )=1]} :(ij)=xiyj[gcd(x,y)=1]

https://www.cnblogs.com/sun123zxy/p/12295533.html

得 : 得:
∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}[gcd(x,y )=1] i=1nj=1mxiyj[gcd(x,y)=1]

改 变 枚 举 顺 序 , 枚 举 x 和 y : 改变枚举顺序,枚举x和y: xy:

∑ x = 1 n ∑ y = 1 m ⌊ n x ⌋ ⌊ n y ⌋ [ g c d ( x , y ) = 1 ] sum_{x=1}^nsum_{y=1}^mleft lfloor frac{n}{x} right rfloorleft lfloor frac{n}{y} right rfloor[gcd(x,y)=1] x=1ny=1mxnyn[gcd(x,y)=1]

∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ [ g c d ( i , j ) = 1 ] sum_{i=1}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft lfloor frac{n}{j} right rfloor[gcd(i,j)=1] i=1nj=1minjn[gcd(i,j)=1]

后 面 套 用 前 面 得 : 后面套用前面得:

∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ ∑ d ∣ i    d ∣ j μ ( d ) sum_{i=1}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft lfloor frac{n}{j} right rfloorsum_{d|i;d|j}mu(d) i=1nj=1minjndidjμ(d)

枚 举 d 得 : 枚举d得: d

∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ n j ⌋ [ d ∣ g c d ( i , j ) ] sum_{d=1}^{min(n,m)}mu(d)sum_{i=1}^nsum_{j=1}^mleft lfloor frac{n}{i} right rfloorleft lfloor frac{n}{j} right rfloor[d|gcd(i,j)] d=1min(n,m)μ(d)i=1nj=1minjn[dgcd(i,j)]

由 于 [ d ∣ g c d ( i , j ) ] 成 立 的 条 件 为 d 是 g c d ( i , j ) 的 约 数 , 所 以 可 以 把 枚 举 i , j 变 换 为 枚 举 d i , d j , 从 而 [ 1 ∣ g c d ( i , j ) ] 可 以 省 略 。 得 : 由于[d|gcd(i,j)]成立的条件为d是gcd(i,j)的约数,所以可以把枚举i,j变换为枚举di,dj,从而[1|gcd(i,j)]可以省略。得: [dgcd(i,j)]dgcd(i,j)i,jdi,dj[1gcd(i,j)]

∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n i d ⌋ ⌊ n j d ⌋ sum_{d=1}^{min(n,m)}mu(d)sum_{i=1}^{left lfloor frac{n}{d} right rfloor}sum_{j=1}^{left lfloorfrac{m}{d}right rfloor}left lfloor frac{n}{id} right rfloorleft lfloor frac{n}{jd} right rfloor d=1min(n,m)μ(d)i=1dnj=1dmidnjdn

∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ⌊ n i d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n j d ⌋ sum_{d=1}^{min(n,m)}mu(d)sum_{i=1}^{left lfloor frac{n}{d} right rfloor}left lfloor frac{n}{id} right rfloorsum_{j=1}^{left lfloorfrac{m}{d}right rfloor}left lfloor frac{n}{jd} right rfloor d=1min(n,m)μ(d)i=1dnidnj=1dmjdn

令 f ( x ) = ∑ i = 1 x ⌊ x i ⌋ , 则 : 令blue{f(x)=sum_{i=1}^xleft lfloor frac{x}{i} right rfloor},则: f(x)=i=1xix

∑ d = 1 m i n ( n , m ) μ ( d ) f ( n d ) f ( m d ) sum_{d=1}^{min(n,m)}mu(d)f(frac{n}{d})f(frac{m}{d}) d=1min(n,m)μ(d)f(dn)f(dm)

O ( n ) 处 理 μ 和 其 前 缀 和 , O ( n n ) 处 理 f , O ( n ) 询 问 分 块 , 总 复 杂 度 为 O ( n n + T n ) red{O(n)处理mu和其前缀和,O(nsqrt n)处理f,O(sqrt n)询问分块,总复杂度为O(nsqrt n+Tsqrt n)} O(n)μO(nn )fO(n )O(nn +Tn )

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 5e4 + 10;

ll mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;

ll f[N];

void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }

    for(int i = 1;i < N; i++) {
        mu[i] += mu[i - 1];
    }

    for(int i = 1;i < N; i++) {
        ll ans = 0;
        for(int l = 1, r;l <= i; l = r + 1) {
            r = i / (i / l);
            ans += (r - l + 1) * (i / l);
        }
        f[i] = ans;
    }
}

ll Ans(ll n, ll m)
{
    ll ans = 0;
    ll k = min(n, m);

    for(ll l = 1, r;l <= k; l = r + 1) {
        r = min(n / (n / l), m / (m / l));
        ans += (mu[r] - mu[l - 1]) * f[m / l] * f[n / l];
    }
    return ans;
}


void solve() {
    int T;
    Mobi();
    cin >> T;
    while(T--) {
        ll n, m;
        cin >> n >> m;
        cout << Ans(n, m) << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P3312 [SDOI2014]数表

求 解 ∑ i = 1 n ∑ j = 1 m ∑ d ∣ i    d ∣ j d [ ∑ d ∣ i    d ∣ j d ≤ a ] 求解sum_{i=1}^nsum_{j=1}^msum_{d|i;d|j}d[sum_{d|i;d|j}dleq a] i=1nj=1mdidjd[didjda]

令 F ( x ) = ∑ i ∣ x i , 则 得 : 令blue {F(x)=sum_{i|x}i},则得: F(x)=ixi

∑ i = 1 n ∑ j = 1 m F ( g c d ( i , j ) ) [ F ( g c d ( i , j ) ) ≤ a ] sum_{i=1}^nsum_{j=1}^m F(gcd(i,j))[F(gcd(i,j))leq a] i=1nj=1mF(gcd(i,j))[F(gcd(i,j))a]

∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m F ( d ) [ g c d ( i , j ) = d ] [ F ( d ) ≤ a ] sum_{d=1}^{min(n,m)}sum_{i=1}^nsum_{j=1}^m F(d)[gcd(i,j)=d][F(d)leq a] d=1min(n,m)i=1nj=1mF(d)[gcd(i,j)=d][F(d)a]

∑ d = 1 m i n ( n , m ) F ( d ) [ F ( d ) ≤ a ] ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] sum_{d=1}^{min(n,m)}F(d)[F(d)leq a]sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=d] d=1min(n,m)F(d)[F(d)a]i=1nj=1m[gcd(i,j)=d]

后 半 部 分 就 套 用 前 面 得 : 后半部分就套用前面得:

∑ d = 1 m i n ( n , m ) F ( d ) [ F ( d ) ≤ a ] ∑ d ′ = 1 m i n ( ⌊ n d ⌋ , ⌊ m d ⌋ ) μ ( d ′ ) ⌊ n d d ′ ⌋ ⌊ m d d ′ ⌋ sum_{d=1}^{min(n,m)}F(d)[F(d)leq a]sum_{d^{'}=1}^{min(left lfloor frac{n}{d} right rfloor, left lfloor frac{m}{d} right rfloor)}mu(d^{'})left lfloor frac{n}{dd^{'}} right rfloor left lfloor frac{m}{dd^{'}} right rfloor d=1min(n,m)F(d)[F(d)a]d=1min(dn,dm)μ(d)ddnddm

令 T 替 换 d d ′ 得 : 令T替换dd^{'}得: Tdd

∑ T = 1 m i n ( n , m ) ∑ d ∣ T F ( d ) μ ( T d ) ⌊ n T ⌋ ⌊ m T ⌋ [ F ( d ) ≤ a ] sum_{T=1}^{min(n,m)}sum_{d|T}F(d)mu(frac{T}{d})left lfloor frac{n}{T} right rfloor left lfloor frac{m}{T} right rfloor[F(d)leq a] T=1min(n,m)dTF(d)μ(dT)TnTm[F(d)a]

∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T F ( d ) μ ( T d ) [ F ( d ) ≤ a ] sum_{T=1}^{min(n,m)}left lfloor frac{n}{T} right rfloor left lfloor frac{m}{T} right rfloorsum_{d|T}F(d)mu(frac{T}{d})[F(d)leq a] T=1min(n,m)TnTmdTF(d)μ(dT)[F(d)a]

令 f ( x ) = ∑ d ∣ x F ( d ) μ ( x d ) [ F ( d ) ≤ a ] 得 : 令blue{f(x)=sum_{d|x}F(d)mu(frac{x}{d})[F(d)leq a]}得: f(x)=dxF(d)μ(dx)[F(d)a]

∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ f ( T ) sum_{T=1}^{min(n,m)}left lfloor frac{n}{T} right rfloor left lfloor frac{m}{T} right rfloor f(T) T=1min(n,m)TnTmf(T)

O ( n ) 处 理 μ , O ( n l o g n ) 处 理 F , 对 于 每 次 询 问 的 a 值 可 以 离 线 排 序 , 树 状 数 组 维 护 f , 处 理 时 间 为 O ( n l o g 2 n ) , O ( n    l o g n ) 询 问 分 块 , 总 时 间 复 杂 度 为 O ( n l o g 2 n ) + T n    l o g n red{O(n)处理mu,O(nlogn)处理F,对于每次询问的a值可以离线排序,树状数组维护f,处理时间为O(nlog^{2}n),O(sqrt n; logn)询问分块,总时间复杂度为O(nlog^2n)+Tsqrt n; logn} O(n)μO(nlogn)Fa线fO(nlog2n)O(n logn)O(nlog2n)+Tn logn

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x3f3f3f3f
#define lc u << 1
#define rc u << 1 | 1
#define m (l + r) / 2
#define mid (t[u].l + t[u].r) / 2
#define lowbit(x) x & (-x)
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;

const int N = 1e5 + 1;
ll mod = (1ll * 1) << 31;

struct node {
    int id;
    ll data;
}F[N];
struct Node {
    int nn, mm, id;
    ll a;
}q[N];

int cnt, prime[N];
bool is_prime[N];
int mu[N];

bool cmp_F(node a, node b) {
    return a.data < b.data;
}

bool cmp_Q(Node a, Node b) {
    return a.a < b.a;
}

inline void init()
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }

    for(int i = 1;i < N; i++) {
        F[i].id = i;
        for(int j = 1;j * i < N; j++) {
            F[i * j].data += i;
        }
    }
    sort(F + 1, F + N, cmp_F);

}

ll t[N];
ll ans[N];

inline void add(int x, int v) {
    while(x < N) {
        t[x] = (t[x] + v) % mod;
        if(t[x] > mod)
            t[x] %= mod;
        x += lowbit(x);
    }
}

inline ll query(int x) {
    ll ans = 0;
    while(x) {
        ans = (ans + t[x]) % mod;
        if(ans > mod)
            ans %= mod;
        x -= lowbit(x);
    }
    return ans;
}

inline ll Calc(int nn, int mm) {
    if(nn > mm)
        swap(nn, mm);

    ll ans = 0;
    for(int l = 1, r;l <= nn; l = r + 1) {
        r = min(nn / (nn / l), mm / (mm / l));
        ans = (ans + 1ll * (nn / l) * (mm / l) % mod * (query(r) - query(l - 1)) % mod) % mod;
    }
    return ans;
}

//struct SegMent {
//    int l, r;
//    int sum;
//}t[N << 2];
//
//void push_up(int u) {
//    t[u].sum = t[lc].sum + t[rc].sum;
//}
//
//void build(int u, int l, int r) {
//    t[u].l = l;
//    t[u].r = r;
//    if(l == r) {
//        t[u].sum = a[l];
//        return ;
//    }
//    build(lc, l, m);
//    build(rc, m + 1, r);
//    push_up(u);
//}
//
//void update(int u, int p, int v) {
//    if(t[u].l == t[u].r) {
//        t[u].sum += v;
//        return ;
//    }
//    if(p <= mid) update(lc, p, v);
//    else update(rc, p, v);
//    push_up(u);
//}
//
//int query(int u, int ql, int qr) {
//    if(ql <= t[u].l && t[u].r <= qr) {
//        return t[u].sum;
//    }
//    int ans = 0;
//    if(ql <= mid)
//        ans += query(lc, ql, qr);
//    if(qr > mid)
//        ans += query(rc, ql, qr);
//    return ans;
//}

void solve() {
    init();
    int T;
    scanf("%d",&T);
    for(int i = 1;i <= T; i++) {
        scanf("%d%d%lld",&q[i].nn,&q[i].mm, &q[i].a);
        q[i].id = i;
    }
    sort(q + 1, q + T + 1, cmp_Q);

    int now = 1;
    for(int i = 1;i <= T; i++) {
        while(now < N && F[now].data <= q[i].a) {
            for(int j = 1;j * F[now].id < N; j++) {
                add(j * F[now].id, mu[j] * F[now].data);
            }
            now++;
        }
        ans[q[i].id] = (Calc(q[i].nn, q[i].mm) % mod + mod) % mod;
    }
    for(int i = 1;i <= T; i++) {
        printf("%lldn",ans[i]);
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P3172 [CQOI2015]选数

求 解 ∑ i = L H ∑ j = L H . . . ∑ x = L H [ g c d ( i , j . . . x ) = k ] 求解sum_{i=L}^Hsum_{j=L}^H...sum_{x=L}^H[gcd(i,j...x)=k] i=LHj=LH...x=LH[gcd(i,j...x)=k]

本 题 求 n 个 数 的 g c d 为 k 的 个 数 , 根 据 上 面 套 路 , 将 H / k , L / k , 这 样 就 只 用 求 n 个 数 的 g c d 为 1 的 个 数 了 , 注 意 : 如 果 L 整 除 k , 则 L = L / k , 否 则 L = L / k + 1 , 就 是 向 上 取 整 , 那 么 有 一 种 办 法 非 常 好 , 就 让 L / k + ( k − 1 k ) , 即 : 本题求n个数的gcd为k的个数,根据上面套路,将H/k,L/k,这样就只用求n个数的gcd为1的个数了,注意:如果L整除k,则L=L/k,否则L=L/k+1,就是向上取整,那么有一种办法非常好,就让blue{L/k+(frac{k-1}{k})},即: ngcdkH/k,L/kngcd1LkL=L/kL=L/k+1L/k+(kk1)

∑ i = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ j = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ . . . ∑ x = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ [ g c d ( i , j . . . x ) = 1 ] sum_{i={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}sum_{j={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}...sum_{x={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}[gcd(i,j...x)=1] i=kL1+1kHj=kL1+1kH...x=kL1+1kH[gcd(i,j...x)=1]

∑ i = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ j = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ . . . ∑ x = ⌊ L − 1 k ⌋ + 1 ⌊ H k ⌋ ∑ d ∣ i    d ∣ j    . .    d ∣ x μ ( d ) sum_{i={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}sum_{j={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}...sum_{x={left lfloor frac{L-1}{k} right rfloor+1}}^{left lfloor frac{H}{k}right rfloor}sum_{d|i;d|j;..;d|x}mu(d) i=kL1+1kHj=kL1+1kH...x=kL1+1kHdidj..dxμ(d)

枚 举 d , 令 l = ⌊ L − 1 k ⌋ + 1 , r = ⌊ H k ⌋ : 枚举d,令blue{l=left lfloor frac{L-1}{k} right rfloor+1,r=left lfloor frac{H}{k}right rfloor}: dl=kL1+1,r=kH

∑ d = 1 r μ ( d ) ∑ i = l r [ d ∣ i ] ∑ j = l r [ d ∣ j ] . . . ∑ x = l r [ d ∣ x ] sum_{d=1}^rmu(d)sum_{i=l}^r[d|i]sum_{j=l}^r[d|j]...sum_{x=l}^r[d|x] d=1rμ(d)i=lr[di]j=lr[dj]...x=lr[dx]

只 有 当 i , j . . . x 都 是 d 的 倍 数 的 时 候 , 最 终 答 案 + 1 , 根 据 容 斥 原 理 , 那 么 在 [ l , r ] 中 d 倍 数 有 r d − l − 1 d , 对 于 所 有 的 i , j . . . x , 他 们 当 中 所 有 [ l , r ] 的 d 的 倍 数 的 个 数 有 ( r d − l − 1 d ) n , 即 为 : 只有当i,j...x都是d的倍数的时候,最终答案+1,根据容斥原理,那么在[l,r]中d倍数有blue{frac{r}{d}-frac{l-1}{d}},对于所有的i,j...x,他们当中所有[l,r]的d的倍数的个数有blue{(frac{r}{d}-frac{l-1}{d})^n},即为: ij...xd+1[l,r]ddrdl1ij...x[l,r]d(drdl1)n

∑ d = 1 r μ ( d ) ∗ ( r d − l − 1 d ) n sum_{d=1}^{r}mu(d)*(frac{r}{d}-frac{l-1}{d})^n d=1rμ(d)(drdl1)n

这 里 的 H 非 常 大 , 如 果 用 线 性 筛 去 处 理 μ , 会 直 接 W a 掉 , 因 为 没 法 处 理 到 1 0 9 次 方 那 么 大 的 前 缀 和 , 数 组 也 开 不 了 那 么 大 。 后 果 : 这里的H非常大,如果用线性筛去处理mu,会直接Wa掉,因为没法处理到10^9次方那么大的前缀和,数组也开不了那么大。后果: H线μWa109

在这里插入图片描述
这 里 的 A C 可 能 就 是 一 小 部 分 的 运 气 罢 了 。 如 果 用 线 性 筛 , R E 的 R E , W A 的 W A , 所 以 推 荐 用 杜 教 筛 取 筛 。 这里的AC可能就是一小部分的运气罢了。如果用线性筛,RE的RE,WA的WA,所以推荐用杜教筛取筛。 AC线REREWAWA

设 f ( d ) = μ ( d ) , S ( r ) = ∑ d = 1 n f ( d ) , 这 里 的 S 就 是 要 求 的 前 缀 和 。 blue{设f(d)=mu(d),S(r)=sum_{d=1}^nf(d),这里的S就是要求的前缀和。} f(d)=μ(d),S(r)=d=1nf(d)S
我 们 选 择 g = I , 则 ∑ i = 1 r ( f ∗ g ) i = ∑ i = 1 r ( μ ∗ I ) i = ∑ i = 1 r ε ( i ) = 1 。 我们选择blue{g=I},则sum_{i=1}^r(f*g)i=sum_{i=1}^r(mu*I)i=sum_{i=1}^rvarepsilon (i)=1。 g=I,i=1r(fg)i=i=1r(μI)i=i=1rε(i)=1

枚 举 y : 枚举y: y

∑ y = 1 r g ( y ) ∑ x = 1 ⌊ r y ⌋ ) f ( x ) sum_{y=1}^rg(y)sum_{x=1}^{left lfloor frac{r}{y} right rfloor)}f(x) y=1rg(y)x=1yr)f(x)

∑ y = 1 r g ( y ) S ( ⌊ r y ⌋ ) sum_{y=1}^rg(y)S(left lfloor frac{r}{y} right rfloor) y=1rg(y)S(yr)

∑ i = 1 r ( f ∗ g ) i = g ( 1 ) S ( r ) + ∑ y = 2 r g ( y ) S ( ⌊ r y ⌋ ) sum_{i=1}^r(f*g)i =g(1)S(r)+sum_{y=2}^rg(y)S(left lfloor frac{r}{y} right rfloor) i=1r(fg)i=g(1)S(r)+y=2rg(y)S(yr)

S ( r ) = ∑ i = 1 r ( f ∗ g ) i − ∑ y = 2 r g ( y ) S ( ⌊ r y ⌋ ) g ( 1 ) S(r)=frac{sum_{i=1}^r(f*g)i-sum_{y=2}^rg(y)S(left lfloor frac{r}{y} right rfloor)}{g(1)} S(r)=g(1)i=1r(fg)iy=2rg(y)S(yr)

当 g = I 时 , 即 : 当g=I时,即: g=I

S ( r ) = 1 − ∑ y = 2 r S ( ⌊ r y ⌋ ) red{S(r)=1-sum_{y=2}^rS(left lfloor frac{r}{y} right rfloor)} S(r)=1y=2rS(yr)

杜 教 筛 的 复 杂 度 为 O ( n 2 3 ) , 比 线 性 筛 还 要 快 一 点 , 总 时 间 复 杂 度 为 O ( n 2 3 ) 。 red{杜教筛的复杂度为O(nfrac{2}{3}),比线性筛还要快一点,总时间复杂度为O(n^{frac{2}{3}})。} O(n32)线O(n32)

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const ll mod = 1e9 + 7;

const int N = 1e6 + 10;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll sum[N];

ll n, L, H, k;

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(int i = 1;i < N; i++) {
        sum[i] = (sum[i - 1] + mu[i]) % mod;
    }
}

map<ll , ll> mp;

ll Calc(ll x) {
    if(x < N)
        return sum[x];
    if(mp[x])
        return mp[x];
    ll num = 1;
    for(int l = 2, r;l <= x; l = r + 1) {
        r = x / (x / l);
        num = (num - Calc(x / l) * (r - l + 1) % mod + mod) % mod;
    }
    return mp[x] = num;
}

ll Ans() {
    ll ans = 0;
    for(ll l = 1, r;l <= H;l = r + 1) {
        r = min(H / (H / l), (L / l) ? L / (L / l) : H + 2);
        ans = (ans + (Calc(r) - Calc(l - 1) + mod) % mod * quick_pow((H / l) - (L / l), n) % mod + mod) % mod;
    }
    return (ans + mod) % mod;
}

void solve() {
    cin >> n >> k >> L >> H;
    L = (L - 1) / k; // 因为后面需要L-1,所以这里干脆就不+1了,但是含义不同
    H = H / k;
    Mobi();
    cout << Ans() << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

AT5200 [AGC038C] LCMs

求 解 ∑ i = 1 N ∑ j = 1 N l c m ( A i , A j ) 求解sum_{i=1}^{N}sum_{j=1}^Nlcm(A_i,A_j) i=1Nj=1Nlcm(Ai,Aj)

莫 比 乌 斯 反 演 处 理 的 一 般 都 是 枚 举 变 量 之 间 的 关 系 , 所 以 我 们 要 让 A i 和 A j 变 为 i 和 j 的 形 式 。 莫比乌斯反演处理的一般都是枚举变量之间的关系,所以我们要让A_i和A_j变为i和j的形式。 AiAjij

想 要 用 i 和 j 表 示 A i 和 A j 并 且 不 遗 漏 任 何 的 A , 所 以 让 A 等 于 某 个 i , 就 是 让 c n t i = ∑ d = 1 N [ A d = i ] , 统 计 所 有 A 等 于 某 个 i 的 个 数 , 即 c n t i , j 也 同 样 如 此 , 如 下 所 示 : 想要用i和j表示A_i和A_j并且不遗漏任何的A,所以让A等于某个i,就是让cnt_i=blue{sum_{d=1}^N[A_d=i]},统计所有A等于某个i的个数,即cnt_i,j也同样如此,如下所示: ijAiAjAAicnti=d=1N[Ad=i]Aicntij

∑ i = 1 N ∑ j = 1 N c n t i c n t j l c m ( i , j ) sum_{i=1}^{N}sum_{j=1}^Ncnt_icnt_jlcm(i,j) i=1Nj=1Ncnticntjlcm(i,j)

这 样 还 不 够 , 因 为 i 只 能 是 [ 1 , N ] 的 , 当 A i 中 有 些 值 大 于 N 的 话 , 再 枚 举 i 从 [ 1 , N ] 就 会 漏 掉 大 于 N 的 A i 的 情 况 , 所 以 想 要 统 计 所 有 情 况 , 即 让 N = A i 中 最 大 的 数 即 可 , 即 M = max ⁡ i = 1 N A i 。 这样还不够,因为i只能是[1,N]的,当Ai中有些值大于N的话,再枚举i从[1,N]就会漏掉大于N的Ai的情况,所以想要统计所有情况,即让N=Ai中最大的数即可,即blue{M=max_{i=1}^N {{ A_i }}}。 i[1,N]AiNi[1,N]NAiN=AiM=maxi=1NAi
所 以 我 们 需 要 反 演 的 式 子 为 : 所以我们需要反演的式子为:

∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ l c m ( i , j ) sum_{i=1}^{M}sum_{j=1}^Mcnt_i ⋅cnt_j ⋅lcm(i,j) i=1Mj=1Mcnticntjlcm(i,j)

∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ i j g c d ( i , j ) sum_{i=1}^{M}sum_{j=1}^Mcnt_i ⋅cnt_j ⋅frac{ij}{gcd(i,j)} i=1Mj=1Mcnticntjgcd(i,j)ij

∑ k = 1 M ∑ i = 1 M ∑ j = 1 M c n t i ⋅ c n t j ⋅ i j k [ g c d ( i , j ) = k ] sum_{k=1}^Msum_{i=1}^{M}sum_{j=1}^Mcnt_i ⋅cnt_j ⋅frac{ij}{k[gcd(i,j)=k]} k=1Mi=1Mj=1Mcnticntjk[gcd(i,j)=k]ij

∑ k = 1 M ∑ i = 1 ⌊ M k ⌋ ∑ j = 1 ⌊ M k ⌋ c n t i k ⋅ c n t j k ⋅ i j k 2 k [ g c d ( i , j ) = 1 ] sum_{k=1}^Msum_{i=1}^{left lfloor frac{M}{k} right rfloor}sum_{j=1}^{left lfloor frac{M}{k} right rfloor}cnt_{ik} ⋅cnt_{jk} ⋅frac{ijk^2}{k}[gcd(i,j)=1] k=1Mi=1kMj=1kMcntikcntjkkijk2[gcd(i,j)=1]

∑ k = 1 M k ∑ i = 1 ⌊ M k ⌋ ∑ j = 1 ⌊ M k ⌋ c n t i k ⋅ c n t j k ⋅ i ⋅ j ∑ d ∣ i    d ∣ j μ ( d ) sum_{k=1}^Mksum_{i=1}^{left lfloor frac{M}{k} right rfloor}sum_{j=1}^{left lfloor frac{M}{k} right rfloor}cnt_{ik} ⋅cnt_{jk} ⋅i ⋅jsum_{d|i;d|j}mu(d) k=1Mki=1kMj=1kMcntikcntjkijdidjμ(d)

∑ k = 1 M k ∑ d = 1 ⌊ M k ⌋ μ ( d ) ∑ i = 1 ⌊ M k d ⌋ c n t i k d ⋅ i d ∑ j = 1 ⌊ M k d ⌋ c n t j k d ⋅ j d sum_{k=1}^Mksum_{d=1}^{left lfloor frac{M}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{M}{kd} right rfloor}cnt_{ikd} ⋅idsum_{j=1}^{left lfloor frac{M}{kd} right rfloor}cnt_{jkd} ⋅jd k=1Mkd=1kMμ(d)i=1kdMcntikdidj=1kdMcntjkdjd

∑ k = 1 M k ∑ d = 1 ⌊ M k ⌋ μ ( d ) d 2 ( ∑ i = 1 ⌊ M k d ⌋ c n t i k d ⋅ i ) 2 sum_{k=1}^Mksum_{d=1}^{left lfloor frac{M}{k} right rfloor}mu(d)d^2(sum_{i=1}^{left lfloor frac{M}{kd} right rfloor}cnt_{ikd} ⋅i)^2 k=1Mkd=1kMμ(d)d2(i=1kdMcntikdi)2

令 T = k d 则 : 令T=kd则: T=kd

∑ T = 1 M ( ∑ i = 1 ⌊ M T ⌋ c n t i T ⋅ i ) 2 ∑ k ∣ T μ ( k ) k 2 T k sum_{T=1}^M(sum_{i=1}^{left lfloor frac{M}{T} right rfloor}cnt_{iT} ⋅i)^2sum_{k|T}mu(k)k^2frac{T}{k} T=1M(i=1TMcntiTi)2kTμ(k)k2kT

∑ T = 1 M T ( ∑ i = 1 ⌊ M T ⌋ c n t i T ⋅ i ) 2 ∑ k ∣ T μ ( k ) k sum_{T=1}^MT(sum_{i=1}^{left lfloor frac{M}{T} right rfloor}cnt_{iT} ⋅i)^2sum_{k|T}mu(k)k T=1MT(i=1TMcntiTi)2kTμ(k)k

令 f ( x ) = ∑ i ∣ x μ ( i ) i    ,    g ( x ) = ∑ i = 1 ⌊ M x ⌋ c n t i x ⋅ i = 1 x ∑ x ∣ t t c n t t , 则 最 后 的 式 子 为 : 令blue{f(x)=sum_{i|x}mu(i)i;,;g(x)=sum_{i=1}^{left lfloor frac{M}{x} right rfloor}cnt_{ix} ⋅i=frac{1}{x}sum_{x|t}tcnt_t},则最后的式子为: f(x)=ixμ(i)i,g(x)=i=1xMcntixi=x1xttcntt,

∑ T = 1 M T g 2 ( T ) f ( T ) sum_{T=1}^MTg^2(T)f(T) T=1MTg2(T)f(T)

O ( n ) 处 理 A 的 次 数 , O ( n l o g n ) 处 理 f 和 g , 总 时 间 复 杂 度 为 O ( n l o g n ) red{O(n)处理A的次数,O(nlogn)处理f和g,总时间复杂度为O(nlogn)} O(n)AO(nlogn)fgO(nlogn)

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 5e5 + 10;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int tot;
ll f[N], g[N];

int M, n;
int cnt[N];

void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++tot] = i;
        }
        for (int j = 1; j <= tot && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(int i = 1;i <= M; i++) {
        for(int x = i;x <= M; x += i) {
            f[x] += mu[i] * i;
        }
    }

    for(int x = 1;x <= M; x++) {
        for(int t = x;t <= M; t += x) {
            g[x] += t * cnt[t];
        }
        g[x] /= x;
    }
}

void solve() {
    cin >> n;
    M = n;
    for(int i = 1;i <= n; i++) {
        int x;
        cin >> x;
        cnt[x]++;
        M = max(M, x);
    }
    Mobi();

    ll ans = 0;

    for(int i = 1;i <= M; i++) {
        ans += i * g[i] * g[i] * f[i];
    }

    cout << ans << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

SP5971 LCMSUM - LCM Sum

求 解 ∑ i = 1 n l c m ( i , n ) 求解sum_{i=1}^nlcm(i,n) i=1nlcm(i,n)

⌊ n k ⌋ left lfloor frac{n}{k} right rfloor kn

∑ i = 1 n i n g c d ( i , n ) sum_{i=1}^nfrac{in}{gcd(i,n)} i=1ngcd(i,n)in

∑ k = 1 n ∑ i = 1 n i n k [ g c d ( i , n ) = k ] sum_{k=1}^nsum_{i=1}^nfrac{in}{k[gcd(i,n)=k]} k=1ni=1nk[gcd(i,n)=k]in

∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ i n [ g c d ( i , n k ) = 1 ] sum_{k=1}^nsum_{i=1}^{left lfloor frac{n}{k} right rfloor}in[gcd(i,frac{n}{k})=1] k=1ni=1knin[gcd(i,kn)=1]

n ∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ i [ g c d ( i , n k ) = 1 ] nsum_{k=1}^nsum_{i=1}^{left lfloor frac{n}{k} right rfloor}i[gcd(i,frac{n}{k})=1] nk=1ni=1kni[gcd(i,kn)=1]

n ∑ k ∣ n ∑ i = 1 k i [ g c d ( i , k ) = 1 ] nsum_{k|n}sum_{i=1}^ki[gcd(i,k)=1] nkni=1ki[gcd(i,k)=1]

n ∑ k ∣ n ∑ i = 1 k i ∑ d ∣ i    d ∣ k μ ( d ) nsum_{k|n}sum_{i=1}^kisum_{d|i;d|k}mu(d) nkni=1kididkμ(d)

枚 举 d : 枚举d: d

n ∑ k ∣ n ∑ d ∣ k μ ( d ) ∑ i = 1 ⌊ k d ⌋ i d nsum_{k|n}sum_{d|k}mu(d)sum_{i=1}^{left lfloor frac{k}{d} right rfloor}id nkndkμ(d)i=1dkid

n ∑ k ∣ n ∑ d ∣ k μ ( d ) d ∑ i = 1 ⌊ k d ⌋ i nsum_{k|n}sum_{d|k}mu(d)dsum_{i=1}^{left lfloor frac{k}{d} right rfloor}i nkndkμ(d)di=1dki

n ∑ k ∣ n ∑ d ∣ k μ ( d ) d ⌊ k d ⌋ ∗ ( ⌊ k d ⌋ + 1 ) 2 nsum_{k|n}sum_{d|k}mu(d)dfrac{left lfloor frac{k}{d} right rfloor*(left lfloor frac{k}{d} right rfloor+1)}{2} nkndkμ(d)d2dk(dk+1)

n 2 ∑ k ∣ n { ∑ d ∣ k μ ( d ) ∗ k 2 d + ∑ d ∣ k μ ( d ) ∗ k } frac{n}{2}sum_{k|n}{sum_{d|k}mu(d)*frac{k^2}{d}+sum_{d|k}mu(d)*k} 2nkn{dkμ(d)dk2+dkμ(d)k}

n 2 ∑ k ∣ n k { ∑ d ∣ k μ ( d ) ∗ k d + ∑ d ∣ k μ ( d ) } frac{n}{2}sum_{k|n}k{sum_{d|k}mu(d)*frac{k}{d}+sum_{d|k}mu(d)} 2nknk{dkμ(d)dk+dkμ(d)}

这 时 候 发 现 两 个 狄 利 克 雷 卷 积 , φ ( n ) = μ ∗ i d = ∑ d ∣ n μ ( d ) ∗ n d      ,      ε ( n ) = μ ∗ I = ∑ d ∣ n μ ( d ) 。 所 以 我 们 将 其 替 换 得 : blue{这时候发现两个狄利克雷卷积,varphi (n)=mu*id=sum_{d|n}mu(d)*frac{n}{d};;,;;varepsilon(n) =mu*I=sum_{d|n}mu(d)。所以我们将其替换得:} φ(n)=μid=dnμ(d)dn,ε(n)=μI=dnμ(d)

n 2 ∑ k ∣ n k [ φ ( k ) + ε ( k ) ] frac{n}{2}sum_{k|n}k[varphi(k)+varepsilon(k)] 2nknk[φ(k)+ε(k)]

O ( n ) 处 理 φ , n 询 问 答 案 , 总 复 杂 度 为 O ( n + T n ) 。 red{O(n)处理varphi,sqrt n询问答案,总复杂度为O(n+Tsqrt n)。} O(n)φn O(n+Tn )

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 1e6 + 10;

int phi[N];
bool is_prime[N];
int prime[N];
int tot;

ll f[N];

void Euler()
{
    phi[1] = 1;
    is_prime[1] = true;
    for(int i = 2;i < N; i++){
        if(!is_prime[i]) {
            phi[i] = i - 1;
            prime[++tot] = i;
        }
        for(int j = 1;j <= tot && i * prime[j] < N; j++){
            is_prime[i * prime[j]] = true;
            if(i % prime[j]) {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
            else{
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
        }
    }
    for(int i = 1;i < N; i++) {
        for(int j = i;j < N; j += i) {
            f[j]  += 1ll * phi[i] * i + (i == 1);
        }
    }
}

void solve() {
    Euler();
    int T;
    cin >> T;
    while(T--) {
        int n;
        cin >> n;
        cout << f[n] * n / 2 << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

P5221 Product

求 解 ∏ i = 1 n ∏ j = 1 n l c m ( i , j ) g c d ( i , j ) 求解prod_{i=1}^nprod_{j=1}^nfrac{lcm(i,j)}{gcd(i,j)} i=1nj=1ngcd(i,j)lcm(i,j)

首 先 还 是 把 l c m ( i , j ) 化 简 得 : 首先还是把lcm(i,j)化简得: lcm(i,j)

∏ i = 1 n ∏ j = 1 n i j [ g c d ( i , j ) ] 2 prod_{i=1}^nprod_{j=1}^nfrac{ij}{[gcd(i,j)]^2} i=1nj=1n[gcd(i,j)]2ij

∏ i = 1 n ∏ j = 1 n i j ∗ ∏ i = 1 n ∏ j = 1 n 1 [ g c d ( i , j ) ] 2 prod_{i=1}^nprod_{j=1}^nij*prod_{i=1}^nprod_{j=1}^nfrac{1}{[gcd(i,j)]^2} i=1nj=1niji=1nj=1n[gcd(i,j)]21

我 们 很 容 易 推 出 前 半 部 分 的 数 值 为 ( n ! ) 2 n , 后 半 部 分 的 值 就 是 ∏ i = 1 n ∏ j = 1 n [ g c d ( i , j ) ] 2 的 逆 元 的 平 方 。 blue{我们很容易推出前半部分的数值为(n!)^{2n },后半部分的值就是prod_{i=1}^nprod_{j=1}^n[gcd(i,j)]^2的逆元的平方。} (n!)2ni=1nj=1n[gcd(i,j)]2

所 以 现 在 求 解 : 所以现在求解:

∏ i = 1 n ∏ j = 1 n g c d ( i , j ) prod_{i=1}^nprod_{j=1}^ngcd(i,j) i=1nj=1ngcd(i,j)

∏ k = 1 n ∏ i = 1 n ∏ j = 1 n k [ g c d ( i , j ) = k ] prod_{k=1}^nprod_{i=1}^nprod_{j=1}^nk[gcd(i,j)=k] k=1ni=1nj=1nk[gcd(i,j)=k]

∏ k = 1 n k ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = k ] prod_{k=1}^nk^{sum_{i=1}^nsum_{j=1}^n[gcd(i,j)=k]} k=1nki=1nj=1n[gcd(i,j)=k]

这 个 式 子 的 变 换 , 本 来 是 [ 1 , n ] 中 所 有 的 g c d 累 乘 , 然 后 我 们 单 独 把 g c d ( i , j ) = k 的 拿 出 来 , k 会 有 [ 1 , n ] 的 范 围 , 然 后 我 们 再 将 这 些 k 累 乘 就 会 达 到 之 前 的 效 果 。 这个式子的变换,本来是[1,n]中所有的gcd累乘,然后我们单独把gcd(i,j)=k的拿出来,k会有[1,n]的范围,然后我们再将这些k累乘就会达到之前的效果。 [1,n]gcdgcd(i,j)=kk[1,n]k
不 过 , [ 1 , n ] 中 的 g c d 不 单 单 只 有 一 个 , 可 能 会 有 多 个 相 同 的 g c d , 所 以 变 换 之 后 的 式 子 里 还 需 要 统 计 g c d = k 出 现 的 次 数 , 那 只 需 要 将 他 们 累 加 即 可 。 不过,[1,n]中的gcd不单单只有一个,可能会有多个相同的gcd,所以变换之后的式子里还需要统计gcd=k出现的次数,那只需要将他们累加即可。 [1,n]gcdgcdgcd=k

所 以 没 毛 病 。 继 续 : 所以没毛病。继续:

∏ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ [ g c d ( i , j ) = 1 ] prod_{k=1}^nk^{sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}[gcd(i,j)=1]} k=1nki=1knj=1kn[gcd(i,j)=1]

∏ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ∑ d ∣ i    d ∣ j μ ( d ) prod_{k=1}^nk^{sum_{i=1}^{left lfloor frac{n}{k} right rfloor}sum_{j=1}^{left lfloor frac{n}{k} right rfloor}sum_{d|i;d|j}mu(d)} k=1nki=1knj=1kndidjμ(d)

枚 举 d : 枚举d: d

∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ 1 prod_{k=1}^nk^{sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)sum_{i=1}^{left lfloor frac{n}{kd} right rfloor}sum_{j=1}^{left lfloor frac{n}{kd} right rfloor}1} k=1nkd=1knμ(d)i=1kdnj=1kdn1

∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 red{prod_{k=1}^nk^{sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)(left lfloor frac{n}{kd} right rfloor)^2}} k=1nkd=1knμ(d)(kdn)2

最 终 答 案 为 : 最终答案为:

( n ! ) 2 n ∏ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ( ⌊ n k d ⌋ ) 2 red{(n!)^{2n}prod_{k=1}^nk^{sum_{d=1}^{left lfloor frac{n}{k} right rfloor}mu(d)(left lfloor frac{n}{kd} right rfloor)^2}} (n!)2nk=1nkd=1knμ(d)(kdn)2

O ( n ) 处 理 μ 的 前 缀 和 , n 询 问 指 数 的 分 块 , 可 以 用 欧 拉 降 幂 优 化 , 总 时 间 复 杂 度 为 O ( n + n l o g 2 n red{O(n)处理mu的前缀和,sqrt n询问指数的分块,可以用欧拉降幂优化,总时间复杂度为O(n+nlog_2n} O(n)μ,n O(n+nlog2n

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
// const ll P = 1e9 + 7;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;

const int N = 1000010;
const ll mod = 104857601;

bool is_prime[N];
int prime[N];
int mu[N]; // 莫比乌斯函数
int cnt;

int n;
ll fac = 1;

ll quick_pow(ll a, ll b)
{
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
void Mobi() // 莫比乌斯函数初始化
{
    mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i <= n; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
        mu[i] = mu[i - 1] + mu[i];
        fac = fac * i % mod;
    }
}

ll Ans() {
    ll ans = 1;
    for(int k = 1;k <= n; k++) {
        ll p = 0;
        int t = n / k;
        for(int l = 1, r;l <= t; l = r + 1) {
            r = min(t, t / (t / l));
            p = (p + (mu[r] - mu[l - 1] + mod - 1) * (t / l) % (mod - 1) * (t / l) % (mod - 1)) % (mod - 1);
        }
        ans = ans * quick_pow(k, p) % mod;
    }
    ll k = quick_pow(ans, mod - 2);
    fac = quick_pow(fac, n);
    return quick_pow(k, 2) * fac % mod * fac % mod;
}

void solve() {
    cin >> n;
    Mobi();
    cout << Ans() << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

HDU 6588 Function

求 解 ∑ i = 1 n g c d ( ⌊ i 3 ⌋ , i ) 求解sum_{i=1}^ngcd(left lfloor sqrt[3]i right rfloor,i) i=1ngcd(3i ,i)

我 们 先 将 这 个 一 重 和 式 转 化 为 二 重 和 式 , 得 : 我们先将这个一重和式转化为二重和式,得:

∑ a = 1 ⌊ n 3 ⌋ ∑ i = 1 n g c d ( a , i ) [ ⌊ i 3 ⌋ = a ] sum_{a=1}^{left lfloor sqrt[3]n right rfloor}sum_{i=1}^ngcd(a,i)[left lfloor sqrt[3]i right rfloor=a] a=13n i=1ngcd(a,i)[3i =a]

我 们 来 看 这 个 式 子 , 只 有 当 ⌊ i 3 ⌋ = a 时 , 才 会 有 对 答 案 的 贡 献 为 g c d ( a , i ) , 所 以 a ≤ ⌊ i 3 ⌋ < a + 1 , a 3 ≤ i ≤ ( a + 1 ) 3 − 1 , 所 以 上 式 转 化 为 : 我们来看这个式子,只有当left lfloor sqrt[3]i right rfloor=a时,才会有对答案的贡献为gcd(a,i),所以blue{a leq left lfloor sqrt[3]i right rfloor < a+1,a^3 leq i leq (a+1)^3-1},所以上式转化为: 3i =agcd(a,i)a3i <a+1a3i(a+1)31

∑ a = 1 ⌊ n 3 ⌋ ∑ i = a 3 m i n ( n , ( a + 1 ) 3 − 1 ) g c d ( a , i ) red{sum_{a=1}^{left lfloor sqrt[3]n right rfloor}sum_{i=a^3}^{min(n,(a+1)^3-1)}gcd(a,i)} a=13n i=a3min(n,(a+1)31)gcd(a,i)

然 后 我 们 将 这 个 二 重 和 式 拆 开 得 : 然后我们将这个二重和式拆开得:

∑ a = 1 ⌊ n 3 ⌋ − 1 ∑ i = a 3 m i n ( n , ( a + 1 ) 3 − 1 ) g c d ( a , i ) + ∑ i = ( ⌊ n 3 ⌋ ) 3 n g c d ( ⌊ n 3 ⌋ , i ) {color{Brown}sum_{a=1}^{left lfloor sqrt[3]n right rfloor-1}sum_{i=a^3}^{min(n,(a+1)^3-1)}gcd(a,i)+sum_{i=(left lfloor sqrt[3]n right rfloor)^3}^ngcd(left lfloor sqrt[3]n right rfloor, i)} a=13n 1i=a3min(n,(a+1)31)gcd(a,i)+i=(3n )3ngcd(3n ,i)

令 n 3 = N , 并 使 a = i , i = j ( 好 看 一 点 ) 得 : 令sqrt[3]n=N,并使a=i,i=j(好看一点)得: 3n =N使a=i,i=j

∑ i = 1 N − 1 ∑ j = i 3 ( i + 1 ) 3 − 1 g c d ( i , j ) + ∑ j = N 3 n g c d ( N , j ) {color{Brown}sum_{i=1}^{N-1}sum_{j=i^3}^{(i+1)^3-1}gcd(i,j)+sum_{j=N^3}^ngcd(N, j)} i=1N1j=i3(i+1)31gcd(i,j)+j=N3ngcd(N,j)

先 计 算 前 半 部 分 : 先计算前半部分:

∣ − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − ∣ |--------------------------------|

HDU 6833 A Very Easy Math Problem

求 解 ∑ a 1 = 1 n ∑ a 2 = 1 n . . . ∑ a x = 1 n ( ∏ j = 1 x a j k ) f ( g c d ( a 1 , a 2 . . . a x ) ) g c d ( a 1 , a 2 . . . a x ) 求解sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)f(gcd(a_1,a_2...a_x))gcd(a_1,a_2...a_x) a1=1na2=1n...ax=1n(j=1xajk)f(gcd(a1,a2...ax))gcd(a1,a2...ax)
令 d = g c d ( a 1 , a 2 . . . a x ) 得 : 令d=gcd(a_1,a_2...a_x)得: d=gcd(a1,a2...ax)

∑ a 1 = 1 n ∑ a 2 = 1 n . . . ∑ a x = 1 n ( ∏ j = 1 x a j k ) f ( d ) d sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)f(d)d a1=1na2=1n...ax=1n(j=1xajk)f(d)d

枚 举 d 得 : 枚举d得: d

∑ d = 1 n d f ( d ) ∑ a 1 = 1 n ∑ a 2 = 1 n . . . ∑ a x = 1 n ( ∏ j = 1 x a j k ) [ g c d ( a 1 , a 2 . . . a x ) = d ] sum_{d=1}^ndf(d)sum_{a_1=1}^nsum_{a_2=1}^n...sum_{a_x=1}^nleft(prod_{j=1}^xa_j^kright)[gcd(a_1,a_2...a_x)=d] d=1ndf(d)a1=1na2=1n...ax=1n(j=1xajk)[gcd(a1,a2...ax)=d]

∑ d = 1 n d k x + 1 f ( d ) ∑ a 1 = 1 ⌊ n d ⌋ ∑ a 2 = 1 ⌊ n d ⌋ . . . ∑ a x = 1 ⌊ n d ⌋ ( ∏ j = 1 x a j k ) [ g c d ( a 1 , a 2 . . . a x ) = 1 ] sum_{d=1}^nd^{kx+1}f(d)sum_{a_1=1}^{left lfloor frac{n}{d} right rfloor }sum_{a_2=1}^{left lfloor frac{n}{d} right rfloor }...sum_{a_x=1}^{left lfloor frac{n}{d} right rfloor }left(prod_{j=1}^xa_j^kright)[gcd(a_1,a_2...a_x)=1] d=1ndkx+1f(d)a1=1dna2=1dn...ax=1dn(j=1xajk)[gcd(a1,a2...ax)=1]

∑ d = 1 n d k x + 1 f ( d ) ∑ a 1 = 1 ⌊ n d ⌋ ∑ a 2 = 1 ⌊ n d ⌋ . . . ∑ a x = 1 ⌊ n d ⌋ ( ∏ j = 1 x a j k ) ∑ t ∣ a 1    t ∣ a 2    . . .    t ∣ a x μ ( t ) sum_{d=1}^nd^{kx+1}f(d)sum_{a_1=1}^{left lfloor frac{n}{d} right rfloor }sum_{a_2=1}^{left lfloor frac{n}{d} right rfloor }...sum_{a_x=1}^{left lfloor frac{n}{d} right rfloor }left(prod_{j=1}^xa_j^kright)sum_{t|a_1;t|a2;...;t|a_x}mu(t) d=1ndkx+1f(d)a1=1dna2=1dn...ax=1dn(j=1xajk)ta1ta2...taxμ(t)

∑ d = 1 n d k x + 1 f ( d ) ( ∑ i = 1 ⌊ n d ⌋ i k ) x ∑ t ∣ a 1    t ∣ a 2    . . .    t ∣ a x μ ( t ) sum_{d=1}^nd^{kx+1}f(d)left (sum_{i=1}^{left lfloor frac{n}{d} right rfloor }i^kright)^xsum_{t|a_1;t|a2;...;t|a_x}mu(t) d=1ndkx+1f(d)i=1dnikxta1ta2...taxμ(t)

枚 举 t 得 : 枚举t得: t

∑ d = 1 n d k x + 1 f ( d ) ∑ t = 1 ⌊ n d ⌋ μ ( t ) ( ∑ i = 1 ⌊ n d t ⌋ ( i t ) k ) x sum_{d=1}^nd^{kx+1}f(d)sum_{t=1}^{left lfloor frac{n}{d} right rfloor }mu(t)left (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }(it)^kright)^x d=1ndkx+1f(d)t=1dnμ(t)i=1dtn(it)kx

∑ d = 1 n d k x + 1 f ( d ) ∑ t = 1 ⌊ n d ⌋ μ ( t ) t k x ( ∑ i = 1 ⌊ n d t ⌋ i k ) x sum_{d=1}^nd^{kx+1}f(d)sum_{t=1}^{left lfloor frac{n}{d} right rfloor }mu(t)t^{kx}left (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }i^kright)^x d=1ndkx+1f(d)t=1dnμ(t)tkxi=1dtnikx

令 T = d t 并 枚 举 T 得 : 令T=dt并枚举T得: T=dtT

∑ T = 1 n ( ∑ i = 1 ⌊ n d t ⌋ i k ) x T k x ∑ d ∣ T d f ( d ) μ ( T d ) sum_{T=1}^nleft (sum_{i=1}^{left lfloor frac{n}{dt} right rfloor }i^kright)^xT^{kx}sum_{d|T}df(d)mu(frac{T}{d}) T=1ni=1dtnikxTkxdTdf(d)μ(dT)

令 g ( T ) = ∑ d ∣ T d f ( d ) μ ( T d ) , 则 令g(T)=sum_{d|T}df(d)mu(frac{T}{d}),则 g(T)=dTdf(d)μ(dT)

∑ T = 1 n ( ∑ i = 1 ⌊ n T ⌋ i k ) x T k x g ( T ) sum_{T=1}^nleft (sum_{i=1}^{left lfloor frac{n}{T} right rfloor }i^kright)^xT^{kx}g(T) T=1ni=1TnikxTkxg(T)

O ( n l o g n ) 筛 f 和 g , 并 对 T k x g ( T ) 和 ∑ i = 1 ⌊ n T ⌋ i k 做 前 缀 和 , 最 后 n 分 块 计 算 , 复 杂 度 为 O ( n l o g n + T n ) red{O(nlogn)筛f和g,并对T^{kx}g(T)和sum_{i=1}^{left lfloor frac{n}{T} right rfloor }i^k做前缀和,最后sqrt n分块计算,复杂度为O(nlogn+Tsqrt n)} O(nlogn)fgTkxg(T)i=1Tnikn O(nlogn+Tn )

Code


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double pi = acos(-1);

const int N = 2e5 + 10;

ll T, k, x;

int mu[N]; // 莫比乌斯函数
bool is_prime[N];
int prime[N];
int cnt;
ll g[N], f[N];
ll sumG[N], sumi[N];

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans % mod;
}

void Mobi() // 莫比乌斯函数初始化
{
    f[1] = mu[1] = 1;
    is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        f[i] = 1;
        if (!is_prime[i]) {
            mu[i] = -1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    // 筛f函数
    for(int d = 2;d * d < N; d++) {
        for(int i = d * d;i < N; i += d * d) {
            f[i] = 0;
        }
    }
    // 筛g函数
    for(int d = 1;d < N; d++) {
        for(int i = d;i < N; i += d) {
            g[i] = (g[i] + 1ll * d * f[d] % mod * mu[i / d] % mod + mod) % mod;
        }
    }
    // 处理sumG函数和sumi函数前缀和
    for(int i = 1;i < N; i++) {
        ll t = quick_pow(i, k);
        sumi[i] = (sumi[i - 1] + t) % mod;
        sumG[i] = (sumG[i - 1] + quick_pow(t, x) * g[i] % mod) % mod;
    }
}

void solve() {
    cin >> T >> k >> x;
    Mobi();
    while(T--) {
        int n;
        cin >> n;
        ll ans = 0;
        for(int l = 1, r;l <= n; l = r + 1) {
            r = min(n, n / (n / l));
            ans = (ans + (sumG[r] - sumG[l - 1] + mod) % mod * quick_pow(sumi[n / l], x) % mod) % mod;
        }

        cout << ans << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

huntian oy

求 解 ∑ i = 1 n ∑ j = 1 i g c d ( i a − j a , i b − j b ) [ g c d ( i , j ) = 1 ] 求解sum_{i=1}^nsum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1] i=1nj=1igcd(iaja,ibjb)[gcd(i,j)=1]

g c d ( i a − j a , i b − j b ) = i g c d ( a , b ) − j g c d ( a , b ) gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)}-j^{gcd(a,b)} gcd(iaja,ibjb)=igcd(a,b)jgcd(a,b)

题 目 说 g c d ( a , b ) = 1 , 所 以 那 个 复 杂 的 式 子 直 接 变 成 i − j . 题目说gcd(a,b)=1,所以那个复杂的式子直接变成i-j. gcd(a,b)=1ij.

∑ i = 1 n ∑ j = 1 i ( i − j ) [ g c d ( i , j ) = 1 ] sum_{i=1}^nsum_{j=1}^i(i-j)[gcd(i,j)=1] i=1nj=1i(ij)[gcd(i,j)=1]

∑ i = 1 n ∑ j = 1 i i [ g c d ( i , j ) = 1 ] − ∑ i = 1 n ∑ j = 1 i j [ g c d ( i , j ) = 1 ] sum_{i=1}^nsum_{j=1}^ii[gcd(i,j)=1]-sum_{i=1}^nsum_{j=1}^ij[gcd(i,j)=1] i=1nj=1ii[gcd(i,j)=1]i=1nj=1ij[gcd(i,j)=1]

左 边 为 与 i 互 质 的 个 数 , 右 边 为 比 i 小 并 且 互 质 的 数 字 和 , 即 为 : 左边为与i互质的个数,右边为比i小并且互质的数字和,即为: ii

∑ i = 1 n i φ ( i ) − ∑ i = 1 n i φ ( i ) + 1 2 sum_{i=1}^nivarphi (i)-frac{sum_{i=1}^nivarphi (i)+1}{2} i=1niφ(i)2i=1niφ(i)+1

∑ i = 1 n i φ ( i ) − 1 2 frac{sum_{i=1}^nivarphi (i)-1}{2} 2i=1niφ(i)1

因 为 n 有 1 e 9 , 所 以 需 要 杜 教 筛 优 化 。 因为n有1e9,所以需要杜教筛优化。 n1e9

f ∗ g ( n ) = ∑ d ∣ n f ( d ) g ( n d ) = ∑ d ∣ n i d ( d ) ∗ φ ( d ) ∗ g ( n d ) f*g(n)=sum_{d|n}f(d)g(frac{n}{d})=sum_{d|n}id(d)*varphi (d)*g(frac{n}{d}) fg(n)=dnf(d)g(dn)=dnid(d)φ(d)g(dn)

很 显 然 , 设 g = i d , 则 : 很显然,设g=id,则: g=id

f ∗ g ( n ) = ∑ d ∣ n φ ( d ) i d ( n ) = n ∑ d ∣ n φ ( d ) = i d ( n ) ( φ ∗ I ) = i d 2 ( n ) = n 2 f*g(n)=sum_{d|n}varphi (d)id(n)=nsum_{d|n}varphi (d)=id(n)(varphi *I)=id^2(n)=n^2 fg(n)=dnφ(d)id(n)=ndnφ(d)=id(n)(φI)=id2(n)=n2

所 以 得 : S ( n ) = ∑ i = 1 n ( f ∗ g ) i − ∑ i = 2 n g ( i ) S ( n i ) = n ( n + 1 ) ( 2 n + 1 ) 6 − ∑ i = 2 n i S ( n i ) 所以得:S(n)=sum_{i=1}^n(f*g)i-sum_{i=2}^ng(i)S(frac{n}{i})=frac{n(n+1)(2n+1)}{6}-sum_{i=2}^niS(frac{n}{i}) S(n)=i=1n(fg)ii=2ng(i)S(in)=6n(n+1)(2n+1)i=2niS(in)

Code

#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;

#define endl "n"
#define eb emplace_back
#define mem(a, b) memset(a , b , sizeof(a))

const ll INF = 0x3f3f3f3f;
// const ll mod = 998244353;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
const double R = 0.57721566490153286060651209;

template<typename T>
inline void read(T &a) {char c = getchar();T x = 0, f = 1;
    while (!isdigit(c)) {if (c == '-')f = -1;c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0';c = getchar();}a = f * x;
}

const int N = 1e6 + 10;

bool is_prime[N];
int prime[N], cnt;
int phi[N];
ll sum_i_phi[N];

void init() {
    phi[1] = 1;
    for(int i = 2;i < N; i++) {
        if(!is_prime[i]) prime[++cnt] = i, phi[i] = i - 1;
        for(int j = 1;j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = 1;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
    for(int i = 1;i < N; i++) {
        sum_i_phi[i] = (sum_i_phi[i - 1] + 1ll * i * phi[i] % mod) % mod;
    }
}

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
         a = a * a % mod;
         b >>= 1;
    }
    return ans % mod;
}

ll inv2;
ll inv6;

map<ll, ll> mp;

ll S(ll x) {
    if(x < N) return sum_i_phi[x];
    else if(mp[x]) return mp[x];
    ll ans = x * (x + 1) % mod * (2 * x + 1) % mod * inv6 % mod;
    for(int l = 2, r;l <= x; l = r + 1) {
        r = min(x, x / (x / l));
        ans = (ans - 1ll * (r + l) % mod * (r - l + 1) % mod * inv2 % mod * S(x / l)) % mod;
    }
    return mp[x] = ans;
}

void solve() {
    init();
    inv2 = quick_pow(2, mod - 2);
    inv6 = quick_pow(6, mod - 2);
    int _; scanf("%d",&_);
    while(_--) {
        ll n, a, b; scanf("%lld%lld%lld",&n,&a,&b);
        ll ans = (S(n) - 1) % mod;
        ans = ans * inv2 % mod;
        printf("%lldn",(ans % mod + mod) % mod);
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    // cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

HDU 6428 Problem C. Calculate

求 解 ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ϕ ( g c d ( i , j 2 , k 3 ) )      m o d      2 30 求解sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Cphi (gcd(i,j^2,k^3));;mod;;2^{30} i=1Aj=1Bk=1Cϕ(gcd(i,j2,k3))mod230

首 先 要 把 ϕ 和 g c d 分 开 , 即 ϕ ( n ) = ∑ d ∣ n ( ϕ ∗ μ ) ( d ) , 证 明 如 下 : 首先要把phi和gcd分开,即phi(n)=sum_{d|n}(phi*mu)(d),证明如下: ϕgcdϕ(n)=dn(ϕμ)(d)
ϕ ( n ) = ( μ ∗ i d ) ( n ) phi(n)=(mu*id)(n) ϕ(n)=(μid)(n)

∑ d ∣ n μ ( d ) n d sum_{d|n}mu(d)frac{n}{d} dnμ(d)dn

∑ d ∣ n μ ( d ) ∑ d ′ ∣ n d ϕ ( d ′ ) sum_{d|n}mu(d)sum_{d'|frac{n}{d}}phi(d') dnμ(d)ddnϕ(d)

∑ d d ′ ∣ n μ ( d ) ϕ ( d ′ ) sum_{dd'|n}mu(d)phi(d') ddnμ(d)ϕ(d)

∑ d ∣ n ∑ d ′ ∣ d μ ( d ′ ) ϕ ( d d ′ ) sum_{d|n}sum_{d'|d}mu(d')phi(frac{d}{d'}) dnddμ(d)ϕ(dd)

∑ d ∣ n ( ϕ ∗ μ ) ( d ) sum_{d|n}(phi*mu)(d) dn(ϕμ)(d)

所 以 原 式 变 为 : 所以原式变为:

∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ∑ d ∣ i    d ∣ j 2    d ∣ k 3 ( ϕ ∗ μ ) ( d ) sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Csum_{d|i;d|j^2;d|k^3}(phi*mu)(d) i=1Aj=1Bk=1Cdidj2dk3(ϕμ)(d)

∑ d = 1 A ( ϕ ∗ μ ) ( d ) ∑ i = 1    d ∣ i A ∑ j = 1    d ∣ j 2 B ∑ k = 1    d ∣ k 3 C 1 sum_{d=1}^{A}(phi*mu)(d)sum_{i=1;d|i}^Asum_{j=1;d|j^2}^Bsum_{k=1;d|k^3}^C1 d=1A(ϕμ)(d)i=1diAj=1dj2Bk=1dk3C1
left lceil right rceil
观 察 后 面 式 子 , 对 于 一 个 x k , 若 d ∣ x k , 先 把 d 分 解 为 ∏ p i a i . 观察后面式子,对于一个x^k,若d|x^k,先把d分解为prod p_i^{a_i}. xkdxkdpiai.
则 ∏ p i a i ∣ x k , 得 ∏ p i ⌈ a i k ⌉ ∣ x , 所 以 设 则prod p_i^{a_i}|x^k,得prod p_i^{left lceil frac{a_i}{k} right rceil }|x,所以设 piaixkpikaix

f k ( n ) = ∏ p i ⌈ a i k ⌉ f_k(n)=prod p_i^{left lceil frac{a_i}{k} right rceil } fk(n)=pikai

则 : 则:

a n s = ∑ d = 1 A ( ϕ ∗ μ ) ( d ) A f 1 ( d ) B f 2 ( d ) C f 3 ( d ) ans=sum_{d=1}^{A}(phi * mu)(d)frac{A}{f_1(d)}frac{B}{f_2(d)}frac{C}{f_3(d)} ans=d=1A(ϕμ)(d)f1(d)Af2(d)Bf3(d)C

对 于 f k ( n ) , 类 似 分 解 n 的 形 式 。 对于f_k(n),类似分解n的形式。 fk(n)n
分 解 质 因 子 的 过 程 中 , 记 录 质 因 子 的 指 数 , 每 次 质 因 子 + 1 时 , 若 % k = 1 时 , 说 明 该 向 上 取 整 了 , 于 是 f k ( n ) ∗ = 该 质 因 子 . 分解质因子的过程中,记录质因子的指数,每次质因子+1时,若%k=1时,说明该向上取整了,于是f_k(n)*=该质因子. +1%k=1fk(n)=.

由 于 ϕ 和 μ 都 是 积 性 函 数 , 卷 积 之 后 还 是 积 性 函 数 , 设 g ( d ) = ( ϕ ∗ μ ) ( d ) , 则 由于phi和mu都是积性函数,卷积之后还是积性函数,设g(d)=(phi*mu)(d),则 ϕμg(d)=(ϕμ)(d)

ϕ ( n ) = ∑ d ∣ n g ( d ) phi(n)=sum_{d|n}g(d) ϕ(n)=dng(d)

那 么 可 以 得 : 那么可以得:

ϕ ( p k ) = ϕ ( p k − 1 ) + g ( p k ) phi(p^k)=phi(p^{k-1})+g(p^k) ϕ(pk)=ϕ(pk1)+g(pk)

g ( p k ) = ϕ ( p k ) − ϕ ( p k − 1 ) g(p^k)=phi(p^k)-phi(p^{k-1}) g(pk)=ϕ(pk)ϕ(pk1)

g ( p k ) = ( p − 1 ) p k − 1 − ( p − 1 ) p k − 2 g(p^k)=(p-1)p^{k-1}-(p-1)p^{k-2} g(pk)=(p1)pk1(p1)pk2

g ( p k ) = ( p − 1 ) 2 p k − 2 g(p^k)=(p-1)^2p^{k-2} g(pk)=(p1)2pk2

当 我 们 欧 拉 筛 的 过 程 中 : 当我们欧拉筛的过程中:

g ( 1 ) = 1 g(1)=1 g(1)=1

g ( p ) = p − 2 g(p)=p-2 g(p)=p2

g ( p k ) = ( p − 1 ) 2 p k − 2 g(p^{k})=(p-1)^2p^{k-2} g(pk)=(p1)2pk2

g ( p 1 k 1 p 2 k 2 ) = g ( p 1 k 1 ) g ( p 2 k 2 ) g(p_1^{k_1}p_2^{k_2})=g(p_1^{k_1})g(p_2^{k_2}) g(p1k1p2k2)=g(p1k1)g(p2k2)

. . . . . . ...... ......

Code

#include "bits/stdc++.h"
using namespace std;

typedef long long ll;

const ll mod = (1ll << 30);

const int N = 1e7 + 10;
bool is_prime[N];
int prime[N], cnt;
int g[N];
int f1[N], f2[N], f3[N];
int deg[N];

void init() {
    f1[1] = f2[1] = f3[1] = g[1] = 1;
    for(int i = 2;i < N; i++) {
        f1[i] = i;
        if(!is_prime[i]) prime[++cnt] = f2[i] = f3[i] = i, g[i] = i - 2, deg[i] = 1;
        for(int j = 1;j <= cnt && i * prime[j] < N; j++) {
            int now = i * prime[j];
            is_prime[now] = 1;
            if(i % prime[j] == 0) {
                deg[now] = deg[i] + 1;
                int num = 1, tmp = i;
                while(num <= 3 && tmp % prime[j] == 0) num++, tmp /= prime[j];
                if(num == 1) g[now] = g[i] * g[prime[j]];
                else if(num == 2) g[now] = g[i / prime[j]] * (prime[j] - 1) * (prime[j] - 1);
                else g[now] = g[i] * prime[j];
                f2[now] = f2[i] * (deg[now] % 2 == 1 ? prime[j] : 1);
                f3[now] = f3[i] * (deg[now] % 3 == 1 ? prime[j] : 1);
                break;
            }
            else {
                deg[now] = 1;
                f2[now] = f2[i] * f2[prime[j]];
                f3[now] = f3[i] * f3[prime[j]];
                g[now] = g[i] * g[prime[j]];
            }
        }
    }
}

void solve() {
    init();
    int _; scanf("%d",&_);
    while(_--) {
        int A, B, C; scanf("%d%d%d",&A,&B,&C);
        ll ans = 0;
        for(int d = 1;d <= A; d++) {
            ans = (ans + 1ll * g[d] * (A / f1[d]) % mod * (B / f2[d]) % mod * (C / f3[d]) % mod) % mod;
        }
        printf("%lldn",(ans % mod + mod) % mod);
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    // cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

最后

以上就是怕孤单蜡烛为你收集整理的莫比乌斯反演例题集---(自用)参考:大佬1 大佬2 大佬3 大佬4的全部内容,希望文章能够帮你解决莫比乌斯反演例题集---(自用)参考:大佬1 大佬2 大佬3 大佬4所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(136)

评论列表共有 0 条评论

立即
投稿
返回
顶部