bzoj 3944: Sum
传说中的杜教筛,,,
其实就是用狄利克雷卷构造出一个好求的东西,然后表示出要求的东西(好简单啊看起来2333)
虚的不行,这些东西肯定2天之后就什么都不知道了2333
1 #include<bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 6 int n,m,cnt,prime[10000000+5]; 7 LL phi[10000000+5]; 8 int mo[10000000+5]; 9 10 void mobius() 11 { 12 phi[1]=mo[1]=1; m=10000000; 13 for (int i=2; i<=m; i++) 14 { 15 if (!phi[i]) phi[i]=i-1,mo[i]=-1,prime[++cnt]=i; 16 for (int j=1; j<=cnt && i*prime[j]<=m; j++) 17 { 18 if (i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1),mo[i*prime[j]]=-mo[i]; 19 else {phi[i*prime[j]]=phi[i]*prime[j],mo[i*prime[j]]=0; break;} 20 } 21 } 22 for (int i=1; i<=m; i++) phi[i]+=phi[i-1]; 23 for (int i=1; i<=m; i++) mo[i]+=mo[i-1]; 24 } 25 26 map<int , LL > p,q; 27 map<int , bool > vis; 28 LL get_phi(int x){return (x<=m)?phi[x]:p[x];} 29 LL get_mo(int x){return (x<=m)?mo[x]:q[x];} 30 void solve(int x) 31 { 32 if (x<=m) return; 33 int j=1,i; 34 if (vis[x]) return; vis[x]=1; 35 p[x]=((LL)x+1)*x>>1; q[x]=1; 36 while (j<x) 37 { 38 i=j+1; j=x/(x/i); solve(x/i); 39 p[x]-=get_phi(x/i)*(j-i+1); q[x]-=get_mo(x/i)*(j-i+1); 40 } 41 } 42 int main() 43 { 44 int T; 45 scanf("%d",&T); 46 mobius(); 47 while (T--) 48 { 49 scanf("%d",&n); vis.clear(); 50 if (n<=m) printf("%lld %lld\n",phi[n],mo[n]); 51 else{ 52 solve((LL)n); printf("%lld %lld\n",p[n],q[n]); 53 } 54 } 55 return 0; 56 }