题面
https://www.luogu.org/problem/P4213
题解
#include<cstdio> #include<iostream> #include<cstring> #pragma GCC optimize(2) #define ri register int #define maxn 2147483647 #define maxm 3000000 #define maxk 2000 #define LL long long using namespace std; int p[maxm],phi[maxm],miu[maxm],k[maxm],prime[maxm],cnt=0; bool vis[maxm]; LL S1[maxm],S2[maxk]; LL SS1[maxm],SS2[maxk]; bool vis2[maxm]; int T,N; void getS1() { phi[1]=1; for (ri i=2;i<maxm;i++) { if (p[i]==0) { k[i]=p[i]=prime[++cnt]=i; phi[i]=i-1; } for (ri j=1;j<=cnt && i*prime[j]<maxm;j++) { k[i*prime[j]]=p[i*prime[j]]=prime[j]; phi[i*prime[j]]=phi[i]*phi[prime[j]]; if (prime[j]==p[i]) { k[i*prime[j]]*=k[i]; phi[i*prime[j]]=phi[i/k[i]]*phi[prime[j]*k[i]]; if (k[i*prime[j]]==i*prime[j]) phi[i*prime[j]]=i*(prime[j]-1); break; } } } S1[0]=0; for (ri i=1;i<maxm;i++) S1[i]=S1[i-1]+phi[i]; miu[1]=1; for (ri i=2;i<maxm;i++) { if (i==p[i]) miu[i]=-1; else if (k[i]==i) miu[i]=0; else miu[i]=miu[i/k[i]]*miu[k[i]]; } SS1[0]=0; for (ri i=1;i<maxm;i++) SS1[i]=SS1[i-1]+miu[i]; } LL S(int n) { if (n<maxm) return S1[n]; ri x=N/n; if (x<maxk && vis[x]) return S2[x]; vis[x]=true; LL &ans=S2[x]; ans=(LL)n*(n+1)/2; for (ri i=2,j;i<=n;i=j+1) { j=n/(n/i); ans-=(j-i+1)*S(n/i); } return ans; } LL SS(int n) { if (n<maxm) return SS1[n]; ri x=N/n; if (x<maxk && vis2[x]) return SS2[x]; vis2[x]=true; LL &ans=SS2[x]; ans=(LL)1; for (ri i=2,j;i<=n;i=j+1) { j=n/(n/i); ans-=(j-i+1)*SS(n/i); } return ans; } int main(){ scanf("%d",&T); getS1(); for (ri i=1;i<=T;i++) { scanf("%d",&N); memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); printf("%lld %lld\n",S(N),SS(N)); } }
原文地址:https://www.cnblogs.com/shxnb666/p/11427186.html
时间: 2024-11-09 03:08:51