大致内容
线性筛欧拉函数和线性筛素数其实差不多 只是需要用到一些性质: (以下所有p都为素数)
性质1. φ(p)=p−1
这个比较显然,因为素数p除了1之外的因数只有p,因此1到p的整数只有p和p自己不互质
性质2. 若 ,那么
证明:
设b=gcd(n,i) 因为n、i不互质,所以n=k1b,i=k2b 所以n+i=(k1+k2)b,即n+i与i不互质
因为[1,i]中与i不互质的整数n共有i−φ(i)个,且n+i与i不互质
所以(i,2i]中与i不互质的整数也是i−φ(i)个
所以[1,i∗p]中与i不互质的整数有p(i−φ(i))=p∗i−p∗φ(i) 个
即φ(i∗p)=p∗i−(p∗i−p∗φ(i))
因此φ(i∗p)=p∗φ(i)
2018.12.16 Update
今天再看这个性质2居然看不太懂了。。。
另外一个比较好理解的证明方法:
由于φ的另外一种计算方法φ(x)=x∗∏i(1−pi1) 其中pi为x的质因子
且此时i∣p,即i已经包含了i∗p的所有质因子
那么φ(i∗p)=i∗p∗∏i(1−pi1)=p∗φ(i)
性质3. 若 p∤i,那么φ(i∗p)=φ(i)∗(p−1)
由性质1及phi函数为积性函数可知
Code(hdu2824)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int Maxn = 3000000 + 100; int Prime[Maxn], phi[Maxn], NotPrime[Maxn], Cnt; int N, a, b; inline void Get_phi() { for (int i = 2; i <= Maxn; ++i) { if (!NotPrime[i]) { Prime[++Cnt] = i; phi[i] = i - 1; } for (int j = 1; j <= Cnt && i * Prime[j] <= Maxn; ++j) { NotPrime[i * Prime[j]] = 1; if (!(i % Prime[j])) { phi[i * Prime[j]] = phi[i] * Prime[j]; break; } else phi[i * Prime[j]] = phi[i] * (Prime[j] - 1); } } } int main() { #ifndef ONLINE_JUDGE freopen("A.in", "r", stdin); freopen("A.out", "w", stdout); #endif Get_phi(); while (scanf("%d%d", &a, &b) != EOF) { LL Ans = 0; for (int i = a; i <= b; ++i) Ans += phi[i]; cout<<Ans<<endl; } return 0; }
|