Comet OJ - Contest #8E 莫比烏斯函數+歐拉函數

題目大意:

在這裏插入圖片描述
在這裏插入圖片描述

分析:

x=p1a1p2a2...pkakx=p_1^{a_1}p_2^{a_2}...p_k^{a_k}
那麼f(x)=picif(x)=p_i^{c_i}
aia_i爲偶ci=ai/2c_i=a_i/2否則ci=(ai1)/2c_i=(a_i-1)/2
那麼發現f(x)f(x)就是小於xx的最大平方數的根號
那麼
ans=i=1nf(i)ans=\sum_{i=1}^{n}f(i)
枚舉yy考慮有多少個f(x)=yf(x)=y
那麼
ans=y=1nyj=1n/y2(j=)ans=\sum_{y=1}^{\sqrt{n}}y\sum_{j=1}^{n/y^2}(j=無平方因子數)
這就很像一個入門的莫比烏斯函數題完全平方數,
[1,x][1,x]的無平方因子數是Σi=1sqrt(x)μ[i](x/i2)Σ_{i=1}^{sqrt(x)}μ[i]*(x/i^2)
然後就可以將後面的式子換一下,
ans=y=1nyΣi=1n/y2μ[i](n/(i2y2))ans=\sum_{y=1}^{\sqrt{n}}yΣ_{i=1}^{\sqrt{n/y^2}}μ[i]*(n/(i^2y^2))
T=iyT=i*y,
ans=y=1nyΣi=1n/y2μ[i](n/T2)ans=\sum_{y=1}^{\sqrt{n}}yΣ_{i=1}^{\sqrt{n/y^2}}μ[i]*(n/T^2)
換成枚舉TT
ans=T=1n(n/T2)iTμ(i)(T/i)ans=\sum_{T=1}^{\sqrt{n}}(n/T^2)\sum_{i|T}μ(i)(T/i)
有一個性質就是φ(T)=iTμ(i)μ(T/i)φ(T)=\sum_{i|T}μ(i)μ(T/i)
所以
ans=T=1n(n/T2)φ(T)ans=\sum_{T=1}^{\sqrt{n}}(n/T^2)φ(T)
預處理φ(T)φ(T)
那麼對於每次的nn我們就可以在n\sqrt{n}的時間內得出ans
當然也可以對T=1n(n/T2)\sum_{T=1}^{\sqrt{n}}(n/T^2)進行整除分塊

代碼:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>

#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)

#define N 10000005
 
using namespace std;
 
typedef long long ll;
 
int pri[N], phi[N], T, cnt;
bool vis[N];
ll n, ans;

void Pre_Work() {
	phi[1] = 1;
    rep(i, 2, N - 5) {
        if (!vis[i]) pri[++cnt] = i, phi[i] = i - 1;
		for (int j = 1; j <= cnt; j++) {
            if (i * pri[j] > N - 5) break;
            vis[i * pri[j]] = 1;
            if (i % pri[j] != 0) { phi[i * pri[j]] = (ll)phi[i] * (pri[j] - 1); } 
            if (i % pri[j] == 0) { phi[i * pri[j]] = (ll)phi[i] * pri[j]; break; }
        } 	
    }
}
 
int main() {
    Pre_Work();
    scanf("%d", &T);
    while (T--) {
        scanf("%lld", &n);
        ans = 0;
        for (ll i = 1; i * i <= n; i++) ans = ans + 1ll * (n / (i * i)) * phi[i];
        printf("%lld\n", ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章