1030 完美数列 (25分)
Posted bigageyuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1030 完美数列 (25分)相关的知识,希望对你有一定的参考价值。
1030 完美数列 (25分)
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤10?5??)是输入的正整数的个数,p(≤10?9??)是给定的参数。第二行给出 N 个正整数,每个数不超过 10?9??。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
这题蛮有意思的,前几道题我答得飞快,这个有俩个测试点把我卡住了,我当时轻松看了一眼题上来就写了个递归
,俩个测试点没过,一个错误,一个超时,没关系我慢慢分析我出现的错误。。。
#include<stdio.h> //错误版本一。
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int compare(int a[],int i,int j,int p)
{
if(a[j]<=a[i]*p)
return j-i+1;
else
{
int m=compare(a,i+1,j,p);
int n=compare(a,i,j-1,p);
return m>n?m:n;
}
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
printf("%d ",compare(a,0,n-1,p));
return 0;
}
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int compare(int a[],int i,int j,int p)
{
if(a[j]<=a[i]*p)
return j-i+1;
else
{
int m=compare(a,i+1,j,p);
int n=compare(a,i,j-1,p);
return m>n?m:n;
}
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
printf("%d ",compare(a,0,n-1,p));
return 0;
}
上面的那个版本看似很整洁,一个是超时,不用说了,肯定是很多个地方算重复了,可以优化,
那错误在哪里,实质上在数据范围,没错他们都在整形的范围内,但是你中间可是要乘法的啊,
你一乘就溢出了,所以要用到long long 类型才可以。。解决了一个错误,我们来关注超时
#include<stdio.h> //错误版本二。
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
long long m,q;
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
long long m,q;
for(i=0;i<n;i++) //逆这找 超时
{
if(n-i<=max)
break;
for(j=n-1;j>=i;j--)
{
if(j-i+1<=max)
break;
m=a[j];
q=a[i];
q=q*p;
if(m<=q)
{
max=j-i+1;
break;
}
}
}
printf("%d ",max);
{
if(n-i<=max)
break;
for(j=n-1;j>=i;j--)
{
if(j-i+1<=max)
break;
m=a[j];
q=a[i];
q=q*p;
if(m<=q)
{
max=j-i+1;
break;
}
}
}
printf("%d ",max);
return 0;
}
这时我想递归既然超时了,那我就改成循环,做了一些优化,比如明明不用继续下去的就跳出循环结束。。
结果还是超时。。。错在哪里了呢。。。 哦 我想清楚了,我是从后面往前找的,我已经排完序了,
如果从后面往前找的话 ,不具备继承关系,下一次还得从最后开始一个一个试。。虽有有优化但不足。
我们改成前面去找,这样就具备继承关系
#include<stdio.h> //正确版本一
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
long long m,q;
j=0;
for(i=0;i<n;i++)
{
if(n-i<=max)
break;
for(;j<n;j++)
{
m=a[j];
q=a[i];
q=q*p;
if(m<=q)
{
if(j-i+1>max)
max=j-i+1;
}
else
{
break;
}
}
}
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
long long m,q;
j=0;
for(i=0;i<n;i++)
{
if(n-i<=max)
break;
for(;j<n;j++)
{
m=a[j];
q=a[i];
q=q*p;
if(m<=q)
{
if(j-i+1>max)
max=j-i+1;
}
else
{
break;
}
}
}
printf("%d ",max);
return 0;
}
这时我要想既然我开始的时候都排序了,那我们可不可以用二分呢,当然是可以的了。。
#include<stdio.h> //正确版本二
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int erfen(int a[],int t,int low,int high,int p)
{
int mid;
long long m,q;
m=t;
int tem_low=low,tem_high=high;
while(low<=high)
{
mid=(low+high)/2;
q=a[mid];
if(m*p>=q)
{
low=mid+1;
}
else
{
high=mid-1;
}
}
return high;
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
int temp;
int m=0;
for(i=0;i<n;i++)
{
if(n-i<=max)
break;
j=n-1;
m=erfen(a,a[i],m,j,p);
if(m-i+1>max)
max=m-i+1;
}
{
int mid;
long long m,q;
m=t;
int tem_low=low,tem_high=high;
while(low<=high)
{
mid=(low+high)/2;
q=a[mid];
if(m*p>=q)
{
low=mid+1;
}
else
{
high=mid-1;
}
}
return high;
}
int main()
{
int n,p;
scanf("%d %d",&n,&p);
register int i,j;
int a[n];
for(i=0;i<n;i++)
{
scanf("%d",a+i);
}
qsort(a,n,sizeof(int),cmp);
int max=0;
int temp;
int m=0;
for(i=0;i<n;i++)
{
if(n-i<=max)
break;
j=n-1;
m=erfen(a,a[i],m,j,p);
if(m-i+1>max)
max=m-i+1;
}
printf("%d ",max);
return 0;
}
以上是关于1030 完美数列 (25分)的主要内容,如果未能解决你的问题,请参考以下文章