SP3871 GCDEX - GCD Extreme

题目链接

本题解参考这里

积性函数及筛法参考这里

欧拉反演参考这里

思路:

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
using namespace std;

int f[maxn] , g[maxn] , low[maxn] , vis[maxn] , prime[maxn] , k[maxn];//low->最小值因子(带指数) 
int cnt = 0;
void init()
{
    low[1] = g[1] = 1;
    for(int i = 2 ; i <= maxn - 10 ; i ++){
        if(!vis[i]){
            vis[i] = 1 , low[i] = i , g[i] = 2 * i - 1 , prime[++ cnt] = i , k[i] = 1;
        } 
        for(int j = 1 ; j <= cnt && prime[j] * i < maxn ; j ++){
            vis[prime[j] * i] = 1;
            if(i % prime[j] == 0){///即 gcd(i , prime[j]) = p1
                low[i * prime[j]] = low[i] * prime[j];///
                if(low[i] == i){///是否 是p^k 
                    k[prime[j] * i] = k[i] + 1;
                    g[i * prime[j]] = (k[i * prime[j]] + 1) * i * prime[j] - k[i * prime[j]] * i;
                }
                else{
                    g[i * prime[j]] = g[i / low[i]] * g[low[i] * prime[j]];
                }
                break;
            }
            else{
                g[i * prime[j]] = g[i] * g[prime[j]];
                low[i * prime[j]] = prime[j];//prime[j] < p1 
            }
            
        } 
    }
    f[1] = 1;
    for(int i = 2 ; i <= maxn - 10 ; i ++) {
        f[i] = f[i - 1] + 2 * g[i] - i;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    init(); 
    while(cin >> n && n != 0)
    {
    //    debug(f[n]);
        cout << (f[n] - (n * (n + 1) / 2)) / 2 << '\n';
    }
    return 0;
}
View Code

 

posted @ 2021-01-24 02:24  GoodVv  阅读(73)  评论(0编辑  收藏  举报