/* 一开始用了预处理,但是时间复杂程度很高,一直TLE 用了下面犀利的欧拉函数的求法AC了。这题跟hdu2824 差不多的 只是hdu那道要求更高 hdu __int64 long long 都要用%I64d输出地 pku long long %lld 以后这些细节要注意啊!! E(x)表示比x小的且与x互质的正整数的个数。 *若p是素数,E(p)=p-1。 *E(p^k)=p^k-p^(k-1)=(p-1)*P^(k-1) 证:令n=p^k,小于n的正整数数共有n-1即(p^k-1)个,其中与p不质的数共[p^(k-1)-1]个(分别为1*p,2*p,3*p...p(p^(k-1)-1))。 所以E(p^k)=(p^k-1)-(p^(k-1)-1)=p^k-p^(k-1).得证。 *若ab互质,则E(a*b)=E(a)*E(b),欧拉函数是积性函数. *对任意数n都可以唯一分解成n=p1^a1*p2^a2*p3^a3*...*pn^an(pi为素数). 则E(n)=E(p1^a1)*E(p2^a2)*E(p3^a3)*...*E(pn^an) =(p1-1)*p1^(a1-1)*(p2-1)*p2^(a2-1)*...*(pn-1)*pn^(an-1) =(p1^a1*p2^a2*p3^a3*...*pn^an)*[(p1-1)*(p2-1)*(p3-1)*...*(pn-1)]/(p1*p2*p3*...*pn) =n*(1-1/p1)*(1-1/p2)*...*(1-1/pn) * E(p^k) =(p-1)*p^(k-1)=(p-1)*p^(k-2)*p E(p^(k-1))=(p-1)*p^(k-2) ->当k>1时,E(p^k)=E(p*p^(k-1))=E(p^(k-1))*p. (当k=1时,E(p)=p-1.) 由上式: 设P是素数, 若p是x的约数,则E(x*p)=E(x)*p. 若p不是x的约数,则E(x*p)=E(x)*E(p)=E(x)*(p-1). */ //pku 2478 #include <iostream> #include <cstdio> #include <cmath> #include <bitset> #include <cstring> using namespace std; const int N = 1000005; bitset<N>hash; int prime[N / 2]; int phi[N]; long long sum[1000005]; int p; inline void Slove(){ p = 0; for(int i = 2; i < N; i++){ if(!hash[i]){ prime[p++] = i; phi[i] = i - 1; } for(int j = 0; j < p && prime[j] * i < N; j++){ hash[i * prime[j]] = true; if(i % prime[j] == 0){ phi[i * prime[j]] = phi[i] * prime[j]; break; } else{ phi[i * prime[j]] = phi[i] * phi[prime[j]]; } } } } inline void Prime() { int tt = (int)sqrt(1.0 * N); for (int i = 2; i <= tt; i++) if (!hash[i]) for (int j = 2; i * j < N; j++) hash[i * j] = true; p = 0; for (int i = 2; i < N; i++) if (!hash[i]) prime[p++] = i; } inline int Euler(int n) { int temp = n; int result = n; for (int j = 0; j < p && prime[j] <= temp; j++) { if (temp % prime[j] == 0) { result = result / prime[j] * (prime[j] - 1); while (temp % prime[j] == 0) temp /= prime[j]; } } if (temp > 1) result = result / temp * (temp - 1); return result; } int main() { //Prime(); //Euler(); Slove(); int n; sum[2] = 1; for(int i = 3; i < 1000001; i++) sum[i] = sum[i -1] + phi[i]; while (scanf("%d", &n) != EOF) { if (n == 0) break; printf("%lld/n", sum[n]); } } // hdu 2824 #include <iostream> #include <cstdio> #include <cmath> #include <bitset> #include <cstring> using namespace std; const int N = 3000005; bitset<N>hash; int prime[216820]; int phi[N]; //long long sum[N]; int p; inline void Slove(){ p = 0; for(int i = 2; i < N; i++){ if(!hash[i]){ prime[p++] = i; phi[i] = i - 1; } for(int j = 0; j < p && prime[j] * i < N; j++){ hash[i * prime[j]] = true; if(i % prime[j] == 0){ phi[i * prime[j]] = phi[i] * prime[j]; break; } else{ phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } //printf("%d/n", p); } /* // 看来这个方法很搓的 inline void Prime() { //Arrays.fill(hash, (boolean) false); //memset(hash, false, sizeof(hash)); int tt = (int)sqrt(1.0 * N); for (int i = 2; i <= tt; i++) if (!hash[i]) for (int j = 2; i * j < N; j++) hash[i * j] = true; p = 0; for (int i = 2; i < N; i++) if (!hash[i]) prime[p++] = i; } inline int Euler(int n) { //sum[1] = 0; //for (int i = 2; i < 1000005; i++) { int temp = n; int result = n; for (int j = 0; j < p && prime[j] <= temp; j++) { if (temp % prime[j] == 0) { result = result / prime[j] * (prime[j] - 1); while (temp % prime[j] == 0) temp /= prime[j]; } } if (temp > 1) result = result / temp * (temp - 1); return result; } */ int main() { //Prime(); //Euler(); Slove(); //sum[2] = 1; // 预处理MLE //for(int i = 3; i < N; i++) //sum[i] = sum[i -1] + phi[i]; int a, b; while (scanf("%d %d", &a, &b) != EOF) { // if (n == 0) // break; //out.println(sum[n]); long long sum = 0; while(a <= b){ sum += phi[a]; a++; } printf("%I64d/n", sum); } //out.flush(); }