luogu1829クラッシュデジタル形式

トピックリンク

問題

给出\(N、M(N、M \ le10 ^ 7)\)、求\(\和\ limits_ {I = 1} ^ N \和\ limits_ {J = 1} ^ MLCM(I、J)\ )

\(LCM(i、j)が \) iとjの最小公倍数を表します

解決

\(N \ M \)

\ [\和\ limits_ ^ {I 1 =} N \和\ limits_ {J = 1} ^ MLCM(i、j)は\\ = \和\ limits_ {I = 1} ^ N \和\ limits_ {J = 1} ^ M \ FRAC {IJ} {GCD(I、J)} \\ = \和\ limits_ {D = 1} ^ ND \和\ limits_ {I = 1} ^ {\ lfloor \ FRAC {n}は{ D} \ rfloor} \和\ limits_ {J = 1} ^ {\ lfloor \ FRAC {M} {D} \ rfloor} IJ [GCD(I、J)= 1] \\ = \和\ limits_ {D = 1} ^ ND \和\ limits_ {I = 1} ^ {\ lfloor \ FRAC {n}は{D} \ rfloor} \和\ limits_ {J = 1} ^ {\ lfloor \ FRAC {M} {D} \ rfloor} IJ \和\ limits_ {K | I、K | J} \ MU(K)\\ = \和\ limits_ {D = 1} ^ ND \和\ limits_ {k = 1} ^ {\ lfloor \ FRAC {N}、{D} \ rfloor} K ^ 2 \ MU(K)\和\ limits_ {I = 1} ^ {\ lfloor \ FRAC {N} {DK} \ rfloor} iが\ limits_ {J = 1を合計\ } ^ {\ lfloor \ FRAC {M} {DX} \ rfloor} J \]

\(T = DX \)
原式= \(\和\ limits_ {T = 1} ^ N \和\ limits_ {K | T} K ^ 2 \ MU(K)\ FRAC {T} {K} \和\ limits_ {I = 1} ^ {\ lfloor \ FRAC {N}、{T} \ rfloor} I \和\ limits_ {J = 1} ^ {\ lfloor \ FRAC {M} {T} \ rfloor} J \ )

見つかりました2つの後(\ SUMは、\)\することができる\(O(1)\)を算出します。それは前方に対処する方法である({K \和\ limits_ \ | T} K ^ 2 \ MU(K)\ FRAC {T} {K} \) 問題。

明らかに\(K ^ 2 \ MU( k)は\) 乗法関数が設定される\(F(N)= N-2 ^ \ MU(N-)\) この1つは目の前に実際にあるので、(F * ID(K)\)\そのため、畳み込み関数や乗法関数の乗法機能だから、この作品の前に乗法関数です。リニア画面をすることができます。

だから、最終的にどのようにこの機能画面はありません。

ルーチンによれば、集合\(G = *同上\ F ) 観察する\(G(Q ^ P) \) の値が見つかりました(G(Q ^ P)= Q ^ PQ ^ {P-1} \)\

だから画面モードと画面\(\ varphiは\)と似ています。

次に、あなたがすることができます\(O(n)は\)することができません。

実際には、式は、数論ブロック、実際に前処理のボトルネックに見つけることができます。これは、数回のバージョンを聞かれる質問かもしれません。

コード

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 1e7 + 5,mod = 20101009;
ll read() {
    ll x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1; c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = x * 10 + c - '0'; c = getchar();
    }
    return x * f;
}
int vis[N],tot,pri[N];
ll f[N];
inline ll calc(ll x) {
    return (x * (x + 1) / 2) % mod;
}
int main() {
    ll n = read(),m = read();
    if(n > m) swap(n,m);
    f[1] = 1;
    for(int i = 2;i <= n;++i) {
        if(!vis[i]) { pri[++tot] = i;f[i] = (i - 1ll * i * i) % mod; }
        
        for(int j = 1;j <= tot && pri[j] * i <= n;++j) {
            vis[i * pri[j]] = 1;
            if(i % pri[j] == 0) {
                f[i * pri[j]] = 1ll * f[i] * pri[j] % mod;
                break;
            }
            f[i * pri[j]] = f[i] * f[pri[j]];
        }
    }
    ll ans = 0;
    for(int i = 1;i <= n;++i) {
        ans += f[i] * calc(n / i) % mod * calc(m / i) % mod;
        ans %= mod;
    }
    cout<<(ans + mod) % mod;
    return 0;
}

おすすめ

転載: www.cnblogs.com/wxyww/p/luogu1829.html