您的位置:首页 > 运维架构

openjudge练习题-GCD depth

2016-07-14 10:17 134 查看

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);
}
}


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: