积性函数求和小记
(写了一下syf的讨论题,感觉有点压力,所以就去学了一手233)
这位博主很懒,什么都没有留下,整理理论参考下面这位博主:
https://www.cnblogs.com/peng-ym/p/9446555.html
模板题:P4213 【模板】杜教筛(Sum)
AC code:(没开O2优化过了,开了反而没过,玄学优化233)
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
//using namespace tr1;
typedef long long ll;
const int maxn = 5e6;
bool isprime[maxn + 5];
int prime[maxn],cntp,mu[maxn];
ll phi[maxn];
tr1::unordered_map<int, int>mpu; //代替map,加快速度
tr1::unordered_map<int, ll>mpp;
void init(){
memset(isprime,1,sizeof(isprime));
isprime[0] = isprime[1] = 0;
phi[1] = mu[1] = 1;
cntp = 0;
for(int i = 2; i <= maxn; ++i){
if(isprime[i]){
prime[++cntp] = i, phi[i] = i - 1, mu[i] = -1;
}
for(int j = 1; j <= cntp && i * prime[j] <=maxn; ++j){
isprime[i * prime[j]] = 0;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j],
mu[i * prime[j]] = 0;
break ;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 2; i <= maxn; ++i){
mu[i] += mu[i - 1];
phi[i] += phi[i - 1];
}
}
int calc_mu(int x){
if(x <= maxn) return mu[x];
if(mpu[x]) return mpu[x];
int res = 1;
for(unsigned int l = 2,r; l <= x; l = r + 1){ //可能爆int,比如r = 2147483647
r = x / (x / l);
res -= calc_mu(x / l) * (r - l + 1);
}
return mpu[x] = res;
}
ll calc_phi(int x){
if(x <= maxn) return phi[x];
if(mpp[x]) return mpp[x];
ll res = 1LL * x * (x + 1) / 2;
for(unsigned int l = 2, r; l <= x; l = r + 1){ //
r = x / (x / l);
res -= calc_phi(x / l) * (r - l + 1);
}
return mpp[x] = res;
}
int main(){
init();
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("%lld %d\n", calc_phi(n), calc_mu(n));
}
return 0;
}
求t(n)的前缀和,t(n)表示n的约数个数:
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
// 返回1->n每个数约数(因子)的个数和
// T = O(sqrt(n))
ll calc(ll n){
ll res = 0;
for(ll l = 1, r; l <= n; l = r + 1){
r = n / (n / l); // 与(n/i)大小相同的最末尾的位置
res += (n / l) * (r - l + 1); // 当前大小乘以区间个数;
}
return res;
}
int main(){
ll n;
while(~scanf("%lld", &n)){
printf("%lld\n",calc(n));
}
return 0;
}