POJ 2773 Happy 2006------欧几里得 or 欧拉函数。
Happy 2006
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 8359 | Accepted: 2737 |
Description
Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are all relatively prime to 2006.
Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.
Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.
Input
The input contains multiple test cases. For each test case, it contains two integers m (1 <= m <= 1000000), K (1 <= K <= 100000000).
Output
Output the K-th element in a single line.
Sample Input
2006 1 2006 2 2006 3
Sample Output
1 3 5
Source
POJ Monthly--2006.03.26,static
这题,以前做的时候用欧几里得,枚举,2300ms,这次用现在的思路,欧拉来做500ms。
1 /* 2 题意:求第几个与N互素的数字。 3 周期性问题。 4 举例。 5 5的互素有:1.2,3,4 6 很明显: 7 第一个互素是1 8 第二个是 2 9 ...... 10 第五个是 6=5+1; 11 第六个是 8=6+2; 12 这里就存在着周期T. 13 1.需要注意对%==0 的时候的讨论。 14 2.M的值可以为1.要特判。否则对后面的/法,有影响,会RE的。 15 3.基本的思路也很简单,求出N的欧拉值,那么T就求出来了,然后 16 求出它的素数因子,扫一遍,找到余数的那个互素数。 17 */ 18 19 20 #include<iostream> 21 #include<cstdio> 22 #include<cstdlib> 23 #include<cstring> 24 using namespace std; 25 26 27 int opl[1000003]; 28 int s[1000003]; 29 int prime[1000003],len; 30 int f[1000],flen; 31 32 33 void make_prime()//素数打表 34 { 35 int i,j; 36 len=0; 37 for(i=2;i<=1000000;i++) 38 if(s[i]==false) 39 { 40 prime[++len]=i; 41 for(j=i*2;j<=1000000;j=j+i) 42 s[j]=true; 43 } 44 } 45 46 void make_Euler()//欧拉函数[1,1000000]全部打表。 47 { 48 int i,j; 49 make_prime(); 50 for(i=2;i<=1000000;i++) 51 opl[i]=i; 52 opl[1]=0; 53 for(i=1;i<=len;i++) 54 for(j=prime[i];j<=1000000;j=j+prime[i]) 55 opl[j]=opl[j]/prime[i]*(prime[i]-1); 56 } 57 58 void make_dEuler(int n)//素因子装在f[] 59 { 60 int i; 61 flen=0; 62 for(i=2;i*i<=n;i++) 63 if(n%i==0) 64 { 65 while(n%i==0) 66 n=n/i; 67 f[++flen]=i; 68 } 69 if(n!=1) 70 f[++flen]=n; 71 } 72 73 int make_ini(int n,int k1) 74 { 75 int i,j; 76 int num=0; 77 make_dEuler(n); 78 memset(s,false,sizeof(s)); 79 for(i=1;i<=flen;i++) 80 for(j=f[i];j<=n;j=j+f[i]) 81 s[j]=true; 82 for(i=1;i<=n;i++) 83 if(s[i]==false) 84 { 85 num++; 86 if(num==k1) 87 return i; 88 } 89 } 90 91 int main() 92 { 93 int n,m,sum,k,k1,T; 94 make_Euler(); 95 while(scanf("%d%d",&n,&m)>0) 96 { 97 if(n==1)//特判 98 { 99 printf("%d\n",m); 100 continue; 101 } 102 sum=0; 103 T=opl[n]; 104 if(m%T==0)//!!~ 105 { 106 sum=sum+n*((m-1)/T); 107 sum=sum+make_ini(n,T); 108 } 109 else 110 { 111 sum=sum+n*(m/T); 112 sum=sum+make_ini(n,m%T); 113 } 114 printf("%d\n",sum); 115 } 116 return 0; 117 }