PAT乙级1030. 完美数列(25)

题目链接

https://www.patest.cn/contests/pat-b-practise/1030

给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。
现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数N和p,其中N(<= 105)是输入的正整数的个数,p(<= 109)是给定的参数。第二行给出N个正整数,每个数不超过109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8

思路

暴力破解,先对数列排序,然后从最小的数乘以p,看看有多少数比m*p小

第一种思路是利用 vector+sort 然后嵌套for,这样会超时,可能是嵌套for会超时

第二种思路是用数组保存+sort,一个for,内部调用二分查找修改代码(毕竟是有序递增数列),数列从后往前,用大数除以p,看有多少数大于等于M/p

二分返回大于等于M/p的最小值的下标,大数的下标-最小值的下标 即完美数列个数

代码

代码1

#include<iostream>  
#include<string.h>  
#include<algorithm>    
#include<vector>   
#include<cmath>  
using namespace std;  
int main()  
{     
    //freopen("in.txt" , "r" , stdin);  
	int n,i,j,max=0;
    double p,a[100010];
    //scanf("%d %lf",&n,&p);
	cin>>n>>p;
    for(i=0;i<n;i++)
        cin>>a[i];
		//scanf("%lf",&a[i]);
    sort(a,a+n);
    for(i=0;i<n;i++)
        for(j=i+max-1;j<n;j++)//这里j只需要从i+max-1开始考虑,先保证长度
        {
            if(a[i]*p<a[j])
                break;
            else
                max =j-i+1;
        }
    //printf("%d\n",max);
	cout<<max<<endl;
       return 0;
}  

代码2

有一个测试样例超时 22分

#include<iostream>
#include<string.h>
#include<algorithm>  
#include<vector> 
#include<cmath>
using namespace std;
int main()
{  
  //freopen("in.txt" , "r" , stdin);
  int nums,p,num;
  vector<int>v;
  cin>>nums>>p;
  for(int i=0;i<nums;i++)
  {
    cin>>num;
    v.push_back(num);
  }
  sort(v.begin(),v.end());//从小到大排序
  
  vector<int>::iterator iter1;//迭代器遍历vector 
  vector<int>::iterator iter2;//迭代器遍历vector 
  int count=0,count_max=0;
  int key=0;
    if(p<1)
    cout<<"0"<<endl;
  else
  {
    if(nums==1)
      cout<<"1"<<endl;
    else
      {    
        int s=nums-1;
        for(iter1=v.begin();s!=0;s--)  
        {
          if((*(iter1+s))%p==0)
            key=(*(iter1+s))/p;
          else
            key=(*(iter1+s))/p+1;
          count=0;
          for(iter2=v.begin();iter2<=(iter1+s);iter2++)  
            if(key<=(*iter2))  break;
          count=(iter1+s)-iter2+1;
          if(count>count_max) count_max=count;
          key=count=0;
        }
      cout<<count_max<<endl;
      }
  }
  return 0;
}


代码3

AC

#include<iostream>
#include<string.h>
#include<algorithm>  
#include<vector> 
#include<cmath>
using namespace std;
int BinarySearch(int array[],int left,int right,int value)//基于二分查找修改代码,改为返回大于等于value值得最小下标
{
		//left和right为查找范围
        if (left > right)
        {
            return left;//二分查找此处返回-1 表示没有找得到value这个数
        }
        int mid = left + ((right-left)>>1);
        if (array[mid] > value)
        {
            return BinarySearch(array,left,mid-1,value);
        }
        else if (array[mid] < value)
        {
            return BinarySearch(array,mid+1,right,value);
        }
        else
            return mid;

}
int main()
{	
	//freopen("in.txt" , "r" , stdin);
	int nums,p;
	int a[100000];
	memset(a,0,sizeof(a));
	cin>>nums>>p;
	int i; 
	for(i=0;i<nums;i++)
		cin>>a[i];
	sort(a,a+i);//仅对前i个数进行升序排序
	int count=0,count_max=0; //count记录每个数的完美数列个数,count_max记录最大的完美数列个数
	int key=0;
    if(p<1)//p<1,p乘以最小的数必然比最小的数还小 完美数列个数为0
		cout<<"0"<<endl;
	else
	{
		if(nums==1)//如果数列个数为1 则完美数列个数为1
			cout<<"1"<<endl;
		else
			{		
				for(int s=nums-1;s!=0;s--)  
				{
					if((*(a+s))%p==0)//从大到小取值 判断取到的值是否能整除p,若能整除返回整除的值,
						key=(*(a+s))/p;
					else
						key=(*(a+s))/p+1;//否则返回比整除值得上界
					count=0;
					int j=BinarySearch(a,0,i-1,key);//返回大于等于value 最小值的坐标
					count=s-j+1;
					if(count>count_max) count_max=count;
					key=count=0;
				}
			cout<<count_max<<endl;
			}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值