pku2773(gcd,欧拉函数)(容斥原理+二分)

47 篇文章 0 订阅

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值