51nod1244 莫比乌斯函数之和 杜教筛

虽然都写了,过也过了,还是觉得杜教筛的复杂度好玄学

设f*g=h,∑f=S,

则∑h=∑f(i)S(n/i下取整)

把i=1时单独拿出来,得到

S(n)=(∑h-∑2->n f(i)S(n/i下取整)

右边的部分可以分块解决

递归一下,≤一个阈值的暴力表出来

注意阈值以上的也要记忆化

复杂度不会算,但从本题来看过1e10没问题

 1 #include <bits/stdc++.h>
 2 #define MAX 5000000
 3 using namespace std;
 4 long long a,b,N;
 5 long long miu[MAX+1],p[MAX],ans[MAX];
 6 bool bo[MAX+1];
 7 long long work(long long n)
 8 {
 9     if(n<=MAX) return miu[n];
10     if(ans[N/n]) return ans[N/n];
11     long long ret=1;
12     for(long long j=2;j<=n;)
13     {
14         long long nex=n/(n/j);
15         ret-=(nex-j+1)*work(n/j);
16         j=nex+1;
17     }
18     ans[N/n]=ret;
19     return ret;
20 }
21 int main()
22 {
23     int sum=0;miu[1]=1;
24     for(int i=2;i<=MAX;i++)
25     {
26         if(!bo[i])
27             p[++sum]=i,miu[i]=-1;
28         for(int j=1;j<=sum;j++)
29         {
30             if((long long)p[j]*i<=MAX)
31             {
32                 bo[p[j]*i]=1;
33                 miu[i*p[j]]=-miu[i]*(bool)(i%p[j]);
34             }
35             else break;
36             if(i%p[j]==0) break;
37         }
38     }
39     for(int i=2;i<=MAX;i++)
40         miu[i]+=miu[i-1];
41     scanf("%lld%lld",&a,&b);
42     N=b;
43     long long ans1=work(b);
44     for(int i=1;i<=MAX;i++)
45         ans[i]=0;
46     N=a-1;
47     long long ans2=work(a-1);
48     printf("%lld\n",ans1-ans2);
49     return 0;
50 }

 

posted @ 2017-05-10 16:32  汪立超  阅读(151)  评论(0编辑  收藏  举报