数字

Problem Description
定义f(x) = {比x小,不可以被x整除并且不和x互质的数的个数}(x为正整数)。
当f(x) 是奇数的时候我们称x为“奇真数”。
给出两个数x,y求区间[x,y]内的“奇真数”的个数。
 
Input
 第一行输入一个数N代表测试数据个数(N<=20)。接下来N行每行两个正整数x , y ( 0 < x <= y < 2^31)。
 
Output
 对于每个测试数据输出“奇真数”的个数,每行输出一个结果。
 
Sample Input
2
1 1
1 10
Sample Output
0
4
code:
import java.util.Scanner;


public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner reader = new Scanner(System.in);
		int t = reader.nextInt();
		while(t-->0)
		{
			long x = reader.nextLong();
			long y = reader.nextLong();
			System.out.println(f(y)-f(x-1));
		}
	}
	
	public static long f(long x)
	{
		if(x<(long)2)
		{
			return 0;
		}
		return x/2-1+((long)Math.sqrt((long)x*1.0)%2 == 1?0:-1);
		
	}
}

详解:

题意: 给出一个f(x), 表示不大于x的正整数里,不整除x 且 跟x有大于1的公约数 的数的个数。定义F(x), 为不大于x的正整数里,满足f(x)的值为奇数的数的个数。题目就是求这个F。

分析:

打表找规律的方法我就不说了。这里我们来简单推理证明下。

先来看f(x),“不整除x” 等同于 不是x的约数,“跟x有大于1的公约数” 等同于 不是x的互质数。而且从F的定义知道,我们只需要考虑f(x)的奇偶性即可。

所以, f(x) = x - 约数个数 - 互质数个数 +1 。最后+1是因为,1是约束也是互质数,减了两次所以补回来。

约数个数,我们由基本定理可得,x可写成质数幂累乘的形式,而由计数方法易知 x的约数个数为 (质数的幂+1)的累乘。所以若要使约数为奇数,充要条件是(质数的幂+1)都为奇数,即质数的幂都为偶数。所以此时 x必然是一个平方数。综上,x为平方数,其约数个数为奇数;x为非平方数,其约数个数为偶数

互质数个数,我们自然联想到欧拉函数。

欧拉函数的值为 不大于n的正整数中与n互质的数的个数。这不就是互质数个数么?而且可以证明,欧拉函数在n>2时,值都为偶数。

所以,当x>2时, 若x为平方数,f(x)=x-奇-偶+1,要使f(x)为奇数,则x必为奇数;若x为非平方数,f(x)=x-偶-偶+1,要使f(x)为奇数,则x必为偶数。 当x=1或2时,f(x)=0.

综上,F(x)的值为[3,x]中,奇数平方数+偶数非平方数的个数和,即 偶数个数-偶数^2的个数+奇数^2的个数

而偶数个数为 x/2-1,-1是为了把2减掉。偶数^2个数为 sqrt(x)/2,奇数^2个数为 ( sqrt(x)-(sqrt(x)/2) )-1,这里-1是为了把1减掉。

所以,化简后,F(x) = x/2-1+(sqrt(x)%2? 0: -1).

至此推证完毕。

另外,这题不管我怎么改,用C++交始终是wa(无力吐槽杭电的int64)。。不知道为什么,如果有人有C++能AC的代码,麻烦提供一下,非常感谢~

还有一点就是,x要转成long double后再开根号,或者直接 x*1.0 。用double会wa。。


————转载自:http://blog.csdn.net/tclh123/article/details/7970545

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值