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
这个我之前一直用的欧拉函数,一知半解的情况下解决了这道题目,直到今天发现小伙伴的代码很短,看了看后再次感受到了这个世界深深的恶意。。
思路:(以下内容节选自djz_zxd的博客并稍有更改,地址:http://blog.youkuaiyun.com/djz_zxd?viewmode=contents)
由欧几里得gcd(a,b)=gcd(a+b*t,b),枚举小于m的所有互素的数,然后这些数加上一个m也与m互素,可以由这样的周期性找到第k个的答案。
如果a与b互素,则b×t+a与b也一定互素,反之亦然。
故与m互素的数对m取模具有周期性,根据这个方法我们就可以很快的求出第k个与m互素的数
假设小于m的且与m互素的数有t个,其中第i个是ai,则第t*?+i个与m互素的数是m*?+ai
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int pri[1000000];
int gcd(int a, int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int m,k;
while (~scanf("%d%d",&m,&k))
{
int i,t;
t = 0;
for (i = 1; i <= m; i++)
{
if (gcd(m, i) == 1)
pri[t++] = i;
}
if (k % t)
printf("%d\n",k/t*m+pri[k%t-1]);
else
printf("%d\n",(k/t-1)*m+pri[t-1]);
}
return 0;
}
PS:这道题要注意,用long long的话会超时。经百度后发现long long占64bits,int占32bits,如果处理器是32位CPU的话,处理long long需要至少2个时钟周期,而处理int只需一个,因此,理论上long long的时钟周期更长。看来所有的数据都用long long在避免产生数据溢出的情况下也带来了可能超时的问题。