数学:杜教筛

Luogu4213:杜教筛求积性函数的前n项和

这里的模板是求欧拉函数和莫比乌斯函数前n项和的,如果对于复杂的,需要狄利克雷卷积来推式子

用完全积性函数去拼凑

 1 #include<cstdio>
 2 #include<unordered_map>
 3 #include<iostream>
 4 using namespace std;
 5 const int maxn=5000005;
 6 int n,cnt;
 7 bool vis[maxn];
 8 int mu[maxn],summu[maxn],prim[maxn];
 9 long long phi[maxn],sumphi[maxn];
10 unordered_map<int,int> mpmu;
11 unordered_map<long long,long long> mpphi;
12 inline long long read()
13 {
14     long long x=0,f=1;char ch=getchar();
15     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
16     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 void sieve(int x)
20 {
21     phi[1]=mu[1]=1;
22     for(int i=2;i<=x;i++)
23     {
24         if(!vis[i])
25         {
26             prim[++cnt]=i;
27             mu[i]=-1;phi[i]=i-1;
28         }
29         for(int j=1;j<=cnt&&prim[j]*i<=x;j++)
30         {
31             vis[i*prim[j]]=1;
32             if(i%prim[j]==0)
33             {
34                 phi[i*prim[j]]=phi[i]*prim[j];
35                 break;
36             }
37             else
38             {
39                 mu[i*prim[j]]=-mu[i];
40                 phi[i*prim[j]]=phi[i]*(prim[j]-1);
41             }
42         }
43     }
44     for(int i=1;i<=x;i++)
45     {
46         summu[i]=summu[i-1]+mu[i];
47         sumphi[i]=sumphi[i-1]+phi[i];
48     }
49 }
50 int djsmu(int x)
51 {
52     if(x<=5000000) return summu[x];
53     if(mpmu[x]) return mpmu[x];
54     int ans=1;
55     for(int l=2,r;l<=x;l=r+1)
56     {
57         r=x/(x/l);
58         ans-=(r-l+1)*djsmu(x/l);
59     }
60     return mpmu[x]=ans;
61 }
62 long long djsphi(long long x)
63 {
64     if(x<=5000000) return sumphi[x];
65     if(mpphi[x]) return mpphi[x];
66     long long ans=x*(x+1)/2;
67     for(long long l=2,r;l<=x;l=r+1)
68     {
69         r=x/(x/l);
70         ans-=(r-l+1)*djsphi(x/l);
71     }
72     return mpphi[x]=ans;
73 }
74 int main()
75 {
76     int T;
77     T=read();
78     sieve(5000000);
79     while(T--)
80     {
81         n=read();
82         printf("%lld %d\n",djsphi(n),djsmu(n));    
83     }
84     return 0;
85 }

不开O2过不了

posted @ 2018-09-25 15:13  静听风吟。  阅读(162)  评论(0编辑  收藏  举报