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. 

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

 
 
这题,以前做的时候用欧几里得,枚举,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 }

 

posted @ 2013-08-09 11:33  芷水  阅读(280)  评论(0编辑  收藏  举报