湘潭大学OJ1296GCD

GCD

题目描述

题目描述 a和b的最大公约数(Greatest Common Divisor)是最大的d,d能整除a和b。如果gcd(a,b)=1,我们就称a和b是互素的。给一个区间[a,b],求与6互素的数的个数。比如区间[1,10],与6互素的数为1,5,7,所以一共是3个。

输入 第一行是一个整数K(K≤10,000),表示样例的个数。每个样例占一行,为区间[a,b], (1≤a≤b≤1,000,000,000)
输出 每行输出一个样例的结果

样例输入
2
1 10
1 1000000000
样例输出
3
333333333

解题思路

判断是否与6互素,其实也就是判断是否能够整除2或者3;那我们自然想到搞个循环判断。没错 超时了。时间复杂度大约是10^13。

那我们就会想,可不可以通过区间长度b-a+1来判断中间2的倍数的个数,和3的倍数的个数呢,要注意如果将区间内总的个数 - 2的倍数的个数 - 3的倍数的个数是不对的,因为6的倍数是同时满足的,相当于多减了一遍,所以需要再加上6的倍数的个数,那么思路就很清晰了 ,比如像2的倍数,我们就需要判断区间的左端点是不是2的倍数,不是那就是区间长度/2,若是,则就是区间长度/2+1,但是我们考虑一下3的倍数的个数和6的倍数的个数,如果要这样判断就很麻烦了,举个例子,区间是[5,13] 其中有2个6的倍数,我们就不能简单的通过第一个数字是不是6的倍数来判断了。

所以我就想我们什么时候可以通过区间长度来判断呢,那就是左端点是1的时候,从1开始的区间,若要判断某个数的倍数的个数,就可以通过区间长度除于那个数了。所以,就变成了求[1,b]和[1,a-1]区间内2,3,6的倍数的个数,然后作差就好了。

代码如下

#include<bits/stdc++.h>
using namespace std;

int main() {
	int k;
	scanf("%d",&k);
	while(k--) {
		int a,b;
		scanf("%d%d",&a,&b);
		int bb = b - b/2 - b/3 + b/6; //b/2,b/3,b/6分别是求[1,b]区间内2,3,6倍数的个数
		a--;
		int aa = a - a/2 - a/3 + a/6; //a/2,a/3,a/6分别是求[1,a-1]区间内2,3,6倍数的个数
		printf("%d\n",bb-aa);
	}
} 
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值