码迷,mamicode.com
首页 > 其他好文 > 详细

欧拉函数

时间:2015-03-20 01:20:40      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

POJ 2407 Relatives

 裸题。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt<<1
13 #define rson m+1, r, rt<<1|1
14 #define mnx 2010
15 
16 int fat[mnx];
17 int main(){
18     LL n;
19     while( scanf( "%I64d", &n ) != EOF && n ){
20         int cnt = 0;
21         double m = n;
22         for( LL i = 2; i * i <= n; ++i ){
23             if( n % i == 0 ){
24                 fat[cnt++] = i;
25                 while( n % i == 0 )
26                     n /= i;
27             }
28             if( n == 1 ) break;
29         }
30         if( n != 1 ) fat[cnt++] = n;
31         for( int i = 0; i < cnt; ++i )
32             m *= ( 1.0 - ( 1.0 / fat[i] ) );
33         printf( "%I64d\n", (LL)(m+eps) );
34     }
35     return 0;
36 }
View Code

POJ 1284  Primitive Roots

题意:

就是给出一个奇素数,求出他的原根的个数。

定义:n的原根x满足条件0<x<n,并且有集合{ (xi mod n) | 1 <= i <=n-1 } 和集合{ 1, ..., n-1 }相等

定理:如果p有原根,则它恰有φ(φ(p))个不同的原根,p为素数,当然φ(p)=p-1,因此就有φ(p-1)个原根。。

具体看 这里

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt<<1
13 #define rson m+1, r, rt<<1|1
14 #define mnx 2010
15 
16 int fat[mnx];
17 int main(){
18     LL n;
19     while( scanf( "%I64d", &n ) != EOF && n ){
20         int cnt = 0;
21         n--;
22         double m = n;
23         for( LL i = 2; i * i <= n; ++i ){
24             if( n % i == 0 ){
25                 fat[cnt++] = i;
26                 while( n % i == 0 )
27                     n /= i;
28             }
29             if( n == 1 ) break;
30         }
31         if( n != 1 ) fat[cnt++] = n;
32         for( int i = 0; i < cnt; ++i )
33             m *= ( 1.0 - ( 1.0 / fat[i] ) );
34         printf( "%I64d\n", (LL)(m+eps) );
35     }
36     return 0;
37 }
View Code

POJ 2478 Farey Sequence

欧拉函数求和。用了一个线性求欧拉函数的模板。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt<<1
13 #define rson m+1, r, rt<<1|1
14 #define mnx 1000100
15 
16 int pri[mnx], tot;
17 LL phi[mnx];
18 bool isnot[mnx];
19 void init(){
20     phi[1] = 1;
21     for( int i = 2; i < mnx; ++i ){
22         if( !isnot[i] ){
23             phi[i] = i - 1;
24             pri[tot++] = i;
25         }
26         for( int j = 0; j < tot && i * pri[j] < mnx; ++j ){
27             isnot[i*pri[j]] = 1;
28             if( i % pri[j] == 0 ){
29                 phi[i*pri[j]] = phi[i] * pri[j];
30                 break;
31             }
32             else phi[i*pri[j]] = phi[i] * ( pri[j] - 1 );
33         }
34     }
35 }
36 int main(){
37     init();
38     for( int i = 3; i < mnx; ++i ){
39         phi[i] += phi[i-1];
40     }
41     int n;
42     while( scanf( "%d", &n ) != EOF && n ){
43         printf( "%I64d\n", phi[n] );
44     }
45     return 0;
46 }
View Code

POJ 3090 Visible Lattice Points

从( 0, 0 )看,问右上角在( n, n )的正方形内,能够看到多少个点。就是( x, y ), x与y互质的点都能看到。就是欧拉函数求和 sum, sum*2 + 3就是答案了( 0, 0 ), ( 1, 0 ), ( 0, 1 )三个点也要算上。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt<<1
13 #define rson m+1, r, rt<<1|1
14 #define mnx 2010
15 
16 LL euler( LL x ){
17     double ret = x;
18     for( LL i = 2; i * i <= x; ++i ){
19         if( x % i == 0 )
20             ret *= ( i - 1.0 ) / i;
21         while( x % i == 0 )
22             x /= i;
23     }
24     if( x > 1 ) ret *= ( x - 1.0 ) / x;
25     return (LL)( ret + eps );
26 }
27 int main(){
28     LL n;
29     int cas, kk = 1;
30     scanf( "%d", &cas );
31     while( cas-- ){
32         scanf( "%I64d", &n );
33         printf( "%d %I64d ", kk++, n );
34         LL ans = 0;
35         for( int i = 2; i <= n; ++i )
36             ans += euler( (LL)i );
37         printf( "%I64d\n", ans * 2 + 3 );
38     }
39     return 0;
40 }
View Code

POJ 3696 The Luckiest number

题意:给你一个数L,让你求出最小的一个数能被L整除,这个数满足每一位都是8,问这个数最少有多少位。

首先设这个有k位,则这个数可以表示为 8 / 9 * ( 10^k - 1 )   = L * m

-> 8 * ( 10^k - 1 ) = 9 * L * m;

设 d = gcd( 9L, 8 ) -> 8 / gcd( 9L, 8 ) * ( 10^k - 1 ) = 9 * L / gcd( 9L, 8 ) * m;

因为 8/gcd(9L,8) 与 9L/gcd(9L,8) 互质,则等式成立的话, (10^k-1) % ( 9L/gcd(9L,8) ) == 0;

gcd(9L, 8) = gcd(L, 8)。即 ( 10^k ) % ( 9L/gcd(L,8) ) == 1。。设 q = 9L/gcd(L,8)。。

由欧拉定理,当gcd(10,q) == 1,k = phi(q)是其中一个解。要求最小解,就要枚举phi(q)的所有因子,看是否满足 10^k % ( phi(q)的因子 ) == 1,取最小的那个。

若gcd( 10, q ) != 1,很明显方程无解。用了快速幂和二进制乘法( 因为有可能爆longlong)

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt<<1
13 #define rson m+1, r, rt<<1|1
14 #define mnx 100100
15 
16 LL gcd( LL a, LL b ){
17     return b == 0 ? a : gcd( b, a % b );
18 }
19 LL phi( LL x ){
20     double ret = x;
21     for( LL i = 2; i * i <= x; ++i ){
22         if( x % i == 0 )
23             ret *= ( i - 1.0 ) / i;
24         while( x % i == 0 )
25             x /= i;
26     }
27     if( x > 1 ) ret *= ( x - 1.0 ) / x;
28     return (LL)( ret + eps );
29 }
30 LL m, L;
31 LL mul( LL a, LL b ){
32     LL ret = 0;
33     while( b ){
34         if( b & 1 ) ret = ( ret + a ) % m;
35         a = ( a + a ) % m;
36         b >>= 1;
37     }
38     return ret;
39 }
40 int qpow( LL k ){
41     LL ret = 1, x = 10;
42     while( k ){
43         if( k & 1 ) ret = mul( ret, x ) % m;
44         x = mul( x, x ) % m;
45         k >>= 1;
46     }
47     return ret == 1 ? 1 : 0;
48 }
49 int main(){
50     int kk = 1;
51     while( scanf( "%I64d", &L ) != EOF && L ){
52         m = 9 * L / gcd( L, 8 );
53         LL sum = phi( m ), ans = 1e15;
54         //cout << sum << endl;
55         if( gcd( 10, m ) != 1 ){
56             printf( "Case %d: 0\n", kk++ ); continue;
57         }
58         for( LL i = 1; i * i <= sum; ++i ){
59             if( sum % i == 0 ){
60                 if( qpow( i ) )
61                     ans = min( ans, i );
62                 if( qpow( sum / i) )
63                     ans = min( ans, sum/i );
64             }
65         }
66         printf( "Case %d: %I64d\n", kk++, ans );
67     }
68     return 0;
69 }
View Code

 

欧拉函数

标签:

原文地址:http://www.cnblogs.com/LJ-blog/p/4352334.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!