BZOJ 3944 Sum

杜教筛第一道题!

题面:

3944: Sum

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3843  Solved: 1030
[Submit][Status][Discuss]

Description

Input

一共T+1行
第1行为数据组数T(T<=10)
第2~T+1行每行一个非负整数N,代表一组询问

Output

一共T行,每行两个用空格分隔的数ans1,ans2

Sample Input

6
1
2
8
13
30
2333

Sample Output

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

HINT

反演+杜教筛。

$1=\sum_{i=1}^{n}\sum_{d|i}\mu(d)=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\mu(i)=\sum_{i=1}^{n}S(\lfloor\frac{n}{i}\rfloor)$

$\therefore S(n)=1-\sum_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor)$

 

$S(n)=\sum_{i=1}^{n}\varphi(i)=\sum_{i=1}^{n}[i-\sum_{d|i,d<i}\varphi(d)]=\frac{n(n+1)}{2}-\sum_{i=2}^{n}\sum_{d|i}\varphi(d)=\frac{n(n+1)}{2}-\sum_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor)$

之后预处理前$\frac{2}{3}$,分块回答询问(记忆化搜索)。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 #define LL long long
 6 #define maxn 5400000
 7 #define maxm 100000
 8 #define uint unsigned int
 9 int T,n;
10 int p[670000],cnt;
11 LL mu[maxn+1],varphi[maxn+1];
12 LL ans_mu[maxm+1],ans_varphi[maxm+1];
13 bool book[maxn+1],quest_mu[maxm+1],quest_varphi[maxm+1];
14 void init()
15 {
16     mu[1]=1;
17     varphi[1]=1;
18     for(int i=2;i<=maxn;i++)
19     {
20         if(!book[i])
21         {
22             mu[i]=-1;
23             varphi[i]=i-1;
24             p[++cnt]=i;
25         }
26         for(int j=1;j<=cnt&&1LL*p[j]*i<=maxn;j++)
27         {
28             book[i*p[j]]=true;
29             if(i%p[j])
30             {
31                 mu[i*p[j]]=-mu[i];
32                 varphi[i*p[j]]=varphi[i]*(p[j]-1);
33             }   
34             else
35             {
36                 mu[i*p[j]]=0;
37                 varphi[i*p[j]]=varphi[i]*p[j];
38                 break;
39             }
40         }
41     }
42     for(int i=2;i<=maxn;i++)
43         mu[i]+=mu[i-1],varphi[i]+=varphi[i-1];
44 }
45 LL questmu(uint now)
46 {
47     if(now<=maxn)
48         return mu[now];
49     int last=n/now,nex;
50     if(quest_mu[last])
51         return ans_mu[last];
52     LL save=1;
53     for(uint i=2;i<=now;i=nex+1)
54     {
55         nex=now/(now/i);
56         save-=questmu(now/i)*(nex-i+1);
57     }   
58     quest_mu[last]=true;
59     ans_mu[last]=save;
60     return save;
61 }
62 LL questvarphi(uint now)
63 {
64     if(now<=maxn)
65         return varphi[now];
66     int last=n/now,nex;
67     if(quest_varphi[last])
68         return ans_varphi[last];
69     LL save=(LL)now*(now+1)>>1;
70     for(int i=2;i<=now;i=nex+1)
71     {
72         nex=now/(now/i);
73         save-=questvarphi(now/i)*(nex-i+1);
74     }
75     quest_varphi[last]=true;
76     ans_varphi[last]=save;
77     return save;
78 }
79 int main()
80 {
81     init();
82     scanf("%d",&T);
83     while(T--)
84     {
85         scanf("%d",&n);
86         memset(quest_mu,false,sizeof(quest_mu));
87         memset(quest_varphi,false,sizeof(quest_varphi));
88         printf("%lld %lld\n",questvarphi(n),questmu(n));
89     }
90 }
91 
BZOJ 3944

 

posted @ 2017-07-24 18:43  avancent  阅读(210)  评论(1编辑  收藏  举报