2020年1月17日クイズ

概要リンク

既知の\(F(X)= \ displaystyle \ sum_ {D | X}μ(D)* D \)

次の式の要求の今価値

\(\ displaystyle \ sum_ {i = 1} ^ N \ sum_ {J = 1} ^ NF(GCD(I、J))* F(LCM(I、J))\)

値が大きすぎる場合がありますので、どうぞ9から10 ^ 7 +モジュロ

\(^ 9n≤10\)

エントリー

一行一个整数 n

輸出

一行一个数字,为问题描述所求的值

サンプル入力

4

サンプル出力

9

正解

GCDとLCMは、私がテストを行うときに私は、jは*、結果がそれを書いていない取得、乗算、それらを見てみたかったです。

唯一の乗法関数fが完了しますが、GCDとLCM互いに素ではないではありません見つけるために、仕上げ先生に聞いた後、私の心は涙のバースト。

しかし、今、正のソリューションです\(F(GCD(I、 J))* F(LCM(i、j)は)= F(IJ)\) その理由。

I、J素因数分解は、それがパワーとして0ではありません。

等価GCD、両方のインデックスは分、LCM等価テイクmaxをとり、2つの指標は、C1、C2提供されます。

それ\(P ^ {C1} * P ^ {C2} = P ^ {MAX(C1、C2)+分(C1、C2)} \) ブラインド猫死んだマウス会いました。

このようである\(ANS = \ DisplayStyle {\ sum_ {私は= 1} ^ NF(I)} ^ 2 \)
大{\ {整列} ANS =&\ sum_開始{私は= 1} ^ N- \ sum_ \ [\ {J | I} J * \ MU(J)\\ =&\ sum_ {D = 1} ^ N \ sum_ {i = 1} ^ {N / D} D * \ MU(D)\\ =&\ = {D}。1 sum_のNd ^ * \ MU(D)*(N / D)\\ \整列}終了{} \]
(N / D)は、分割ブロックで計算される(D * \ミュー(\ D)\)プレフィックスと

セット\(G(X)= X * \ MU(X)\)
\ [\大{\開始{整列}(G * ID)(X)&= \ sum_ {D | X} D * \ MU(D )*(N / D)\\
&= \ sum_ {D | X} \ムー(D)\\&= E \ {終了整列}} \] それの魔法、スクリーンボードを教えた後デュ、プットコード

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
const int mod = 1e9+7 , N = 2e6 + 100 , maxn = 2e6;
#define int long long
int n , tot;
map<int,int> w;
int prime[N] , vis[N] , mu[N] , f[N];
void Init(int maxn)
{
    mu[1] = 1;
    for(int i = 2 ; i <= maxn ; ++i)
    {
        if(!vis[i]) prime[++tot] = i , mu[i] = -1;
        for(int j = 1 ; j <= tot && i * prime[j] <= maxn ; ++j)
        {
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(int i = 1 ; i <= maxn ; ++i) f[i] = (f[i-1] + mu[i] * i % mod) % mod;
    return ;
}

int get(int n)
{
    if(n <= maxn) return f[n];
    if(w.count(n)) return w[n];
    int res = 0;
    for(int i = 2 , r ; i <= n ; i = r + 1)
    {
        r = min(n , n / (n / i));
        res = (res + get(n / i) * ((i + r) * (r - i + 1) / 2) % mod) % mod;
    }
    res = ((1 - res) % mod + mod) % mod;
    return w[n] = res;
}

signed main()
{
    freopen("A.in" , "r" , stdin);
    freopen("A.out" , "w" , stdout);
    cin >> n; Init(2e6);
    int ans = 0;
    for(int i = 1 , r; i <= n ; i = r + 1)
    {
        r = min(n , n / (n / i));
        ans = (ans + (get(r) - get(i-1) + mod) % mod * (n / i) % mod) % mod;
    }
    cout << ans * ans % mod << endl;
    fclose(stdin); fclose(stdout); return 0;
}

おすすめ

転載: www.cnblogs.com/R-Q-R-Q/p/12207401.html