首页 > 代码库 > [BZOJ2818] Gcd (数论,欧拉函数,线性筛)

[BZOJ2818] Gcd (数论,欧拉函数,线性筛)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2818

技术分享

 

必须用线性筛。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 10001001;
 5 LL phi[maxn], sum[maxn], n;
 6 bool isprime[maxn];
 7 LL prime[maxn];
 8 int tot;
 9 bool mark[maxn+10];
10 void getphi()
11 {
12     int i,j;
13     phi[1]=1;
14     for(i=2;i<=maxn;i++)
15     {
16         if(!mark[i])
17         {
18             prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。    
19             phi[i]=i-1;//当 i 是素数时 phi[i]=i-1    
20         }
21         for(j=1;j<=tot;j++)    
22         {
23             if(i*prime[j]>maxn)  break;
24             mark[i*prime[j]]=1;//确定i*prime[j]不是素数    
25             if(i%prime[j]==0)//接着我们会看prime[j]是否是i的约数    
26                 {phi[i*prime[j]]=phi[i]*prime[j];break;}
27             else phi[i*prime[j]]=phi[i]*(prime[j]-1);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性
28         }
29     }
30 }
31 
32 namespace fastIO {
33     #define BUF_SIZE 100000
34     //fread -> read
35     bool IOerror = 0;
36     inline char nc() {
37         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
38         if (p1 == pend) {
39             p1 = buf;
40             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
41             if (pend == p1) {
42                 IOerror = 1;
43                 return -1;
44             }
45         }
46         return *p1++;
47     }
48     inline bool blank(char ch) {
49         return ch ==   || ch == \n || ch == \r || ch == \t;
50     }
51     inline int read(LL &x) {
52         char ch;
53         while (blank(ch = nc()));
54         if (IOerror)
55             return 0;
56         for (x = ch - 0; (ch = nc()) >= 0 && ch <= 9; x = x * 10 + ch - 0);
57         return 1;
58     }
59     #undef BUF_SIZE
60 };
61 
62 inline void out(LL x) { 
63     if (x > 9) out(x / 10); 
64     putchar(x % 10 + 0);
65 }
66 
67 signed main() {
68     // freopen("in", "r", stdin);
69     getphi();
70     sum[1] = 0;
71     for(int i = 2; i < maxn; i++) sum[i] = sum[i-1] + phi[i];
72     while(fastIO::read(n)) {
73         LL ret = 0;
74         for(int i = 1; i < tot && prime[i] <= n; i++) {
75             LL p = prime[i];
76             ret += 2LL * sum[n/p] + 1;
77         }
78         out(ret); putchar(\n);
79     }
80     return 0;
81 }

 

[BZOJ2818] Gcd (数论,欧拉函数,线性筛)