public class ProperFractions {
public static long properFractions(long n) {
if (n==1) return 0;
long r=n;
for(long d=2;d*d<=n;d++){
if(n%d == 0){
while(n%d == 0){
n/=d;
}
r-=r/d;
}
}
if(n>1) r-=r/n;
return r;
}
}
这段代码为什么可以求分母为n的最简真分数个数。
所谓最简真分数
首先它是真分数,分子不能比分母大
最简,不能简化,也就是分子不是分母的因子
不是因子就是不能整除
理解了题意再看代码
感觉有点动态规划的意思。首先要懂得什么情况不是最简。
以30为例子:30=235,意味着分母为2/3/5的倍数的时候就不是最简,要做的是把这部分删掉。
有兴趣的话,可以去看看:线性筛和埃氏筛
public long properFractions(long n) {
if (n==1) return 0;
//r:相当于返回值,剩余最简个数
long r=n;
for(long d=2;d*d<=n;d++){
//其实进入这个if的一定是质数,合数在前面已经去掉了,可以拿210看一下
if(n%d == 0){
//这里可以缩小规模,原因是可约分数必然为某因子的倍数,这部分在本次筛选已经去除了,后面不必重复
//举例子:12的因子2*2*3,对于4的倍数,在删掉2的倍数的时候已经删过一遍了,不用重复删,所以这里缩小规模用while
while(n%d == 0){
n/=d;
}
//假设是12,我们知道:待选,1 2 3 4 5 6 7 8 9 10 11 12,对于d=2的情况,2 4 6 8 10 12 都满足,共删除12/2,共6个
r-=r/d;
}
}
//对于最大因子只有一个的情况,比如12=2*2*3,3只有一个,最后一个因子的倍数,没有筛掉,所以这种情况就需要再筛一次;
//8=2*2*2,这种情况,直接把n约到1了,就不用再筛一次
if(n>1) r-=r/n;
return r;
}