1. 程式人生 > >[BZOJ2818] Gcd (數論,歐拉函數,線性篩)

[BZOJ2818] Gcd (數論,歐拉函數,線性篩)

name 歐拉 using pre clu 必須 fast har typedef

題目鏈接: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 (數論,歐拉函數,線性篩)