[bzoj3944] Sum
杜教筛板子
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=6e6+10;
bool vis[N];
int prime[N/10];
int cnt;
ll phi[N],mob[N];
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
inline void init(){
phi[1]=1;
mob[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])prime[++cnt]=i,phi[i]=i-1,mob[i]=-1;
for(int j=1;j<=cnt;j++){
if(i*prime[j]>=N)break;
vis[i*prime[j]]=1;
if(i%prime[j]){
mob[i*prime[j]]=-mob[i];
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}else{
mob[i*prime[j]]=0;
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
for(int i=2;i<N;i++)phi[i]+=phi[i-1],mob[i]+=mob[i-1];
}
map<ll,ll> PHI,MOB;
inline ll calc(ll a,ll b){
if(a&1)return a*(b>>1);
else return b*(a>>1);
}
ll workphi(unsigned int x){
if(x<N)return phi[x];
if(PHI[x])return PHI[x];
//cout<<x<<' '<<N<<endl;
ll ans=calc(x+1,x);
unsigned int u,v;
for(u=2;u<=x;u=v+1){
v=x/(x/u);
ans-=(v-u+1)*workphi(x/u);
}
return PHI[x]=ans;
}
ll workmob(unsigned int x){
//cout<<x;
if(x<N)return mob[x];
if(MOB[x])return MOB[x];
ll ans=1;
unsigned int u,v;
for(u=2;u<=x;u=v+1){
v=x/(x/u);
ans-=(v-u+1)*workmob(x/u);
}
return MOB[x]=ans;
}
void solve(){
ll n;
scanf("%lld",&n);
ll ans1=workphi(n),ans2=workmob(n);
Write(ans1);putchar(' ');Write(ans2);
putchar('\n');
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)solve();
return 0;
}