openjudge练习题-GCD depth

00003:GCD depth

总时间限制:
5000ms
内存限制:
65536kB
描述
In mathematics, the greatest common divisor (gcd), also known as the greatest common factor (gcf), or highest common factor (hcf), of two or more non-zero integers, is the largest positive integer that divides the numbers without a remainder. For example, the GCD of 8 and 12 is 4.
------ From Wikipedia

In this problem,we will introduce a new value related to GCD,which is GCD depth. To GCD depth,follow function will discribe it clearly.

int GCD_depth( int x , int y ) {
if ( y == 0 ) return 0;
else return GCD_depth( y , x%y ) + 1;
}

And we define the GCD depth of y with x is GCD_depth(x,y).For example , GCD depth of 5 with 3 is 4.You can find the GCD depth of two numbers easily ,but LH wants know that: for a number x, how many numbers meet the condition that the GCD depth with x equals to d in the interval [y0,y1]? So please help LH to find the answer quickly.
输入
There are several test cases, each test case contains four Non-negative integers x( 0 <= x <= 200000) , d( 0 <= d <= 30 ),y0 ,y1(0 <= y0 <= y1 <= 10^9),which descripted as above.
The input will finish with the end of file.
输出
For each the case, just output a integer which represent the number of integers meeted the discripted condition.
样例输入
7 2 0 5
3 0 0 1
11 1 2 8
样例输出
2
1
0
题目的意思是,给出一个数x,一个数d,一个范围[y0,y1],要求这个范围内有多少个数字和x的gcd计算出来的深度等于d。

这道题目的最大要求就是时间复杂度了,我一开始的想法是错误的所以一直TLE,后来想到一种线性的办法,各种相加,最多也就100万的计算量,5s的限制太宽松了!

我的方法就是:有一个前提,你先算出0到x的gcd深度存在a数组里面,你就会发现,后来每个数y所对应的gcd深度其实是他取模y%x所对应一开始算出那个深度a[y%x]+2,自己验算一下就知道为什么了。这是个大前提。

                           然后我从y1开始走,用t表示y1,循环x次,这个循环的另外一个条件就是y1要大于x,这是要计算出在[x+1,y1]这个范围内有多少个符合的数,用sum存起来。怎么在循环x次就判断出来呢?就是判断a[t%x]+2是否等于d,如果等于的话,sum+=t/x,当然,如果t%x==0,要特判一下,这种情况的深度是a[t%2]+1。

                          再重复一次,不过这次是范围是[x+1,y0-1]了,不能用y0,因为y0是在范围内的,我只要知道y0-1到x+1这段范围内符合条件的数字,用sub存起来,最后用sum-sub就是x+1到y0符合条件的个数了。

                          这种时间复杂度是多少呢?其实这里一共最多循环了x+1+x+x,x的范围是0到20万,也就是60万的计算量,这道题目却给了5s,我的代码是用了352msAC的

代码如下:

<pre name="code" class="cpp">#include<stdio.h>

int gcd_depth(int x,int y)
{
	if(y == 0)
		return 0;
	return gcd_depth(y, x % y) + 1;
}

int main()
{
	int x,d,y0,y1,n,i,sum,sub,t;
	int a[200005];
	while(scanf("%d%d%d%d",&x,&d,&y0,&y1) != EOF)
	{
		if(x==0)
		{
			if(d==1)
			{
				if(y0>0)
					n=y1-y0+1;
				else if(y0==0&&y1!=0)
					n=y1-y0;
				else if(y1==0)
					n=0;
				printf("%d\n",n);
			}
			else if(d==0&&y0==0)
				printf("1\n");
			else
				printf("0\n");
			continue;
		}
		for(i=0,n=0;i<=x;i++)
		{
			a[i]=gcd_depth(x,i);//初始化0到x的深度,其后所有深度都是由这个+2(如果刚好整除x的话是+1) 
			if(y0<=i&&i<=y1&&a[i]==d)
				n++;
		}
		for(i=0,t=y1,sum=0;i<x&&t>x;i++)//寻找从x+1到y1能有多少个是符合d的,相当于计算x到y1 ,结果放在sum中 
		{
			if(t%x!=0)
			{
				if(a[t%x]+2==d)
					sum+=t/x;
			}
			else
			{
				if(d==2)
					sum+=t/x-1;
			}
			t--;
		} 
		for(i=0,t=y0-1,sub=0;i<x&&t>x;i++) //重复上面操作,但这次是寻找x+1到y0-1,必须减去1,
						//因为y0是包含在计算范围的,y0-1不计算在范围内,最后上面减去下面的就是结果 
		{
			if(t%x!=0)
			{
				if(a[t%x]+2==d)
					sub+=t/x;
			}
			else
			{
				if(d==2)
					sub+=t/x-1;
			}
			t--;
		}
		n+=sum-sub;
		printf("%d\n",n);
	}
} 


 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值