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 } 

 

posted @ 2017-04-12 21:13  ws_ccd  阅读(139)  评论(0编辑  收藏  举报