[bzoj4804] 欧拉心算
莫比乌斯反演
自己的做法比较神奇
让s[x]表示phi的前缀和 ,f[x]表示1-n中gcd(i,j)=x的个数然后可以发现f[x]=s[n/x]*2-1 (这里是下取整)
然后就可以分块了
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+1;
bool vis[N];
int prime[1000010],cnt;
ll phi[N];
inline void init(){
phi[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt;j++){
if(i*prime[j]>=N)break;
vis[i*prime[j]]=1;
if(i%prime[j]){
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}else{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
for(int i=2;i<N;i++)phi[i]+=phi[i-1];
}
inline void solve(int n){
int u,v;
ll ans=0;
for(u=1;u<=n;u=v+1){
v=n/(n/u);
int w=n/u;
ans+=(phi[w]*2-1)*(phi[v]-phi[u-1]);
}
printf("%lld\n",ans);
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
solve(n);
}
}