http://162.105.81.212/JudgeOnline/problem?id=2773
题意:给定m, k(1 <= m <= 1000000), K(1 <= K <= 100000000), 询问第k个与m互质的数。
思路:看题目的数据范围是1000000,所以可以先用线性方法计算所有小于M的与M互质的数,储存到数组A[]中,并用tot记录总数。
对于K <= TOT ,直接找到A[K]即可。
对于K > TOT ,取M=5观察与它互质的数的情况:
1 1
2 2
3 3
4 4
5 6 = 1*5+1 = 1*5+A[1]
6 7 = 1*5+2 = 1*5+A[2]
7 8 = 1*5+3 = 1*5+A[3]
8 9 = 1*5+4 = 1*5+A[4]
9 11 = 2*5+1 = 2*5+A[1]
10 12 = 2*5+2 = 2*5+A[2]
11 13 = 2*5+3 = 2*5+A[3]
……
显然对于K > TOT 可以得到A[K] = X*M+A[Y],其中X = (K-1)/4,Y = (K-1)%4+1。
下面是代码,但是有点慢1900+ms。
解法二:也是上面的分析,但是要用到欧拉函数和整数分解来求解,加快了一点。转帖:
欧拉函数的应用。首先是求出m的欧拉函数值phi[m],可知区间[1, m - 1]中有phi[m]个数与m互质。同样,在区间[n*m + 1, (n + 1) * m]中必然也有phi[m]个数与m互质,并且这phi[m]个数与[1 - m - 1]的phi[m]个数是"一一对应"的。用反证法可以证明
假设gcd(a + b, b) != 1, 那么设gcd(a + b, b) = p, 则p是a + b和b的公共素因子的乘积,那么p一定是a, b的公共素因子的乘积,理由如下:
假设a + b = p*q, b = p*t,
a + p*t = p*q -> a = (q - t) * p(q>t)
a与b均含有p这个公约数,p != 1,p是a, b的公共素因子的乘积,这与gcd(a, b) = 1矛盾,所以假设错误。
因此知道[n*m + 1, (n + 1) * m]中必然也有phi[m]个数与m互质,并且这phi[m]个数与[1 - m - 1]的phi[m]个数是"一一对应"的。
所以只要通过k / phi[m]找到第n个区间,然后再枚举区间中的数就可以找到第k个与m互质的数。下面代码用了1500+ms;
看了网上的解题报告,好像最快的要用容斥原理+二分;转帖下别人的思路以后再贴代码吧。
方法就是先求出m以内的所有素数(预处理),然后对m因式分解,m=p1^a1 * p2^a2 * ... * pt^at,然后分别记录下p1, p2, ..., pt。接着是二分k,对于每次二分,用容斥原理去求答案,比如与2不互素的有m / 2个,与3不互素的有m / 3个,与2 * 3 = 6不互素的有m / 6个,因此就是m / 2 + m / 3 - m / 6,显然,这个过程就是个DFS。用了47ms。