【HDOJ 2824】 The Euler function (欧拉筛)
3 100
3042
欧拉筛模板题 刚学欧拉找来做 发现自己板子跑的慢好多 百度来了个配合素数筛的板子 飞一般的感觉
素数筛附带求欧拉的主要原理就是 对于euler(x)
x为素 euler[x] = x-1;
x = y*_p && y%_p != 0 即p为新素数 由于 euler(y) = y(1-1/p1)(1-1/p2)...(1-1/pi) 因此 euler(x) = y*_p(1-1/p1)(1-1/p2)...(1-1/pi)(1-1/_p) = y(1-1/p1)(1-1/p2)...(1-1/pi)(_p-1) = euler(y)*(_p-1)
x = y*_p && y%_p == 0 即p为y的质因子 由于 euler(y) = y(1-1/p1)(1-1/p2)...(1-1/pi) 因此 euler(x) = y*_p(1-1/p1)(1-1/p2)...(1-1/pi) = euler(y)*_p
代码如下:
//弱渣筛法 #include <bits/stdc++.h> #define ll long long using namespace std; //int Euler(int x) //{ // int i,ans = x; // // for(i = 2; i*i <= x; ++i) // { // if(x%i) continue; // ans = ans/i*(i-1); // while(x%i == 0) x /= i; // } // if(x-1) return ans/x*(x-1); // return ans; //} int euler[3333333] = {0}; void InitEuler() { int i,j; for(i = 2; i < 3000000; ++i) { if(euler[i]) continue; euler[i] = i-1; for(j = i*2; j < 3000000; j += i) { if(!euler[j]) euler[j] = j; euler[j] = euler[j]/i*(i-1); } } } int main() { int i,j,a,b; ll sum; // euler[2] = 1; // for(i = 3; i < 3000000; ++i) // { // euler[i] = Euler(i)+euler[i-1]; // } InitEuler(); while(~scanf("%d %d",&a,&b)) { sum = 0; for(i = a; i <= b; ++i) sum += euler[i]; printf("%I64d\n",sum); } return 0; }
大犇素数欧拉筛 #include<stdio.h> #include<stdlib.h> int num[3000024],prime[220000]; bool isprime[3000024]={0}; void eular( ) { int count=0; __int64 k; for( int i=2; i<=3000000; i++ ) { if( !isprime[i] ) { prime[++count]=i; num[i]=i-1; } for( int j=1; j<=count&&( (k=prime[j]*i)<=3000000 );j++ ) { isprime[k]=1; if( i%prime[j]==0 ) { num[k]=num[i]*prime[j]; } else num[k]=num[i]*( prime[j]-1 ); } } } int main( ) { int n,m; eular(); while( scanf( "%d%d",&n,&m )!=EOF ) { __int64 ans=0; for( int i=n; i<=m; i++ ) ans+=num[i]; printf( "%I64d\n",ans ); } return 0; }