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);
}
}
相关文章推荐
- Hadoop配置文件
- opencv下LDA二分类
- VirtualBox内Linux系统怎样与Windows共享文件夹
- 转载其他网站--严格模式
- Linux stat三个时间以及export命令用法
- Boost 实用工具:noncopyable、BOOST_BINARY宏、BOOST_CURRENT_FUNCTION宏、bitset类型
- OpenCV高版本中CImage(CvvImage)取消以后的替代方法
- linux安装jdk
- Linux常用的命令
- pscp命令实现windows和linux文件的传输
- Openstack架构
- 两个一样的tomcat不能同时启动解决方法
- shell学习-3
- Hadoop中HDFS的常用命令
- 非常好!!!---bash转义序列笔记---打印语句printf用法【转】
- Linux基础(10)论grep 与egrep的区别
- nginx php-fpm安装配置
- 关于Linux系统清理/tmp/文件夹 清理时间问题
- 使用ssh-keygen和ssh-copy-id三步实现SSH无密码登录
- 160707、Tomcat 使用 c3p0连接池