orz我还以为要卡很久的常数。。。2333 10s给我过了。。。
对这道题可以挂链表,可能比map快吧。。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 1000050 #define mod 999983 using namespace std; int t,n,tot=0,miu[maxn*5],prime[maxn*5],tot1=0,g1[maxn],g2[maxn],tot2=0; bool vis[maxn*5]; long long phi[maxn*5]; struct link { int nxt,id; long long val; }l1[maxn],l2[maxn]; void get_table() { miu[1]=1;phi[1]=1; for (int i=2;i<=5000000;i++) { if (!vis[i]) { phi[i]=i-1;miu[i]=-1; prime[++tot]=i; } for (int j=1;j<=tot && i*prime[j]<=5000000;j++) { vis[i*prime[j]]=true; if (i%prime[j]) {miu[i*prime[j]]=-miu[i];phi[i*prime[j]]=phi[i]*(prime[j]-1);} else {miu[i*prime[j]]=0;phi[i*prime[j]]=phi[i]*prime[j];break;} } } for (int i=1;i<=5000000;i++) phi[i]+=phi[i-1],miu[i]+=miu[i-1]; } int find(int num,int pos,int type) { int now=(type==1)?g1[num]:g2[num]; while (now) { if (type==1) { if (l1[now].id==pos) return now; else now=l1[now].nxt; } else { if (l2[now].id==pos) return now; else now=l2[now].nxt; } } return 0; } void add(int now,int pos,long long val,int type) { if (type==1) { l1[++tot1].id=pos;l1[tot1].val=val; l1[tot1].nxt=g1[now];g1[now]=tot1; } else { l2[++tot2].id=pos;l2[tot2].val=val; l2[tot2].nxt=g2[now];g2[now]=tot2; } } long long get_phi(long long x) { if (x<=5000000) return phi[x]; long long reg=find(x%mod,x,1);if (reg) return l1[reg].val; long long ret=x*(x+1)/2,l=2,r; while (l<=x) { r=x/(x/l); ret-=get_phi(x/l)*(r-l+1); l=r+1; } add(x%mod,x,ret,1); return ret; } int get_miu(long long x) { if (x<=5000000) return miu[x]; long long reg=find(x%mod,x,2);if (reg) return l2[reg].val; long long ret=1,l=2,r; while (l<=x) { r=x/(x/l); ret-=get_miu(x/l)*(r-l+1); l=r+1; } add(x%mod,x,ret,2); return ret; } int main() { scanf("%d",&t);get_table(); for (int i=1;i<=t;i++) { scanf("%lld",&n); printf("%lld %d\n",get_phi(n),get_miu(n)); } return 0; }