ccf中的一题多解-完美数列和find coins

1.完美数列

思路:在一个递增序列中,确定一个左端点a[i]和一个右端点a[j],使得a[j]<=a[i]*p,并且j-i最大

强行使用O(n^2)进行枚举会超时,但是不要怕,我看到了目前有两种可以解决这个问题的方法,一个是二分法,一个是two pointers方法。

①二分法 O(logn)

从左到右扫描序列中的每一个数a[i],在a[i+1]~a[n-1]进行二分查找第一个超过a[i]*p的数的位置j,不断更新j-i的值然后就可以求得最大的题目要求的量了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int n,p,a[maxn];

//在i+1到n-1范围内查找第一个大于x的数的位置 
int bin(int i,long long x)
{
	int l=i+1,r=n-1,mid;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(a[mid]<=x)
		l=mid+1;
		else
		r=mid;
	}
	return l;
}
int main()
{
	scanf("%d%d",&n,&p);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int ans=1;
	for(int i=0;i<n;i++)
	{
		int j=bin(i,(long long)a[i]*p);
		ans=max(ans,j-i);
	}
	printf("%d\n",ans);
	return 0;
}

这样子还可以进行简化,使用upper_bound函数,upper_bound(startpos,endpos,num);在区间[startpos,endpos)内查找num最大的位置。 

int main()
{
	scanf("%d%d",&n,&p);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int ans=1;
	for(int i=0;i<n;i++)
	{
        
		int j=upper_bound(a+i+1,a+n,(long long)a[i]*p)-a;
		ans=max(ans,j-i);
	}
	printf("%d\n",ans);
	return 0;
} 

 ②two pointers

思路:在这个问题中有一个性质:如果a[j]<=a[i]*p,那么对[i,j]内任意位置k,一定有a[k]<=a[i]*p也成立。令两个下标初值均为0,设置计数器count存放满足条件的最大长度。先让j增加,直到恰好条件不满足,这个时候之后,让i增加,j增加的过程继续,直到j到达序列末端。

int main()
{
	scanf("%d%d",&n,&p);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int i=0,j=0,count=1; 
	while(i<n&&j<n)
	{
        //j不断右移直到恰好不满足条件
		while(j<n&&a[j]<=(long long)a[i]*p)
		{
			count=max(count,j-i+1);
			j++;
		}
		i++;
	}
	printf("%d\n",count);
	return 0;
}

未完待续,20190916 20:23 

2.Find Coins

题目描述
Eva loves to collect coins from all over the universe, including some other planets like Mars.  One day she visited a universal shopping mall which could accept all kinds of coins as payments.  However, there was a special requirement of the payment: for each bill, she could only use exactly two coins to pay the exact amount.  Since she has as many as 105 coins with her, she definitely needs your help.  You are supposed to tell her, for any given amount of money, whether or not she can find two coins to pay for it.

输入描述:
Each input file contains one test case.  For each case, the first line contains 2 positive numbers: N (<=105, the total number of coins) and M(<=103, the amount of money Eva has to pay).  The second line contains N face values of the coins, which are all positive numbers no more than 500.  All the numbers in a line are separated by a space.


输出描述:
For each test case, print in one line the two face values V1 and V2 (separated by a space) such that V1 + V2 = M and V1 <= V2.  If such a solution is not unique, output the one with the smallest V1.  If there is no solution, output "No Solution" instead.

输入例子:
8 15
1 2 8 7 2 4 11 15

输出例子:
4 11
 

①散列法

#include<bits/stdc++.h>
using namespace std;
//solution1:散列 
const int N=1005;
int hash[N];
int main()
{
	int n,m,a;
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a);
		++hash[a];
	}
	for(int i=0;i<N;i++)
	{
		if(hash[i]&&hash[m-i])
		{
			if(i==m-i&&hash[i]<=1)
			{
				continue;
			}
			printf("%d %d\n",i,m-i);
			return 0;
		}
	}
	printf("No Solution\n");
	return 0;
} 

②二分法

//solution2:二分
int a[100010];
int bin(int left,int right,int key)
{
	int mid;
	while(left<=right)
	{
		mid=(right+left)/2;
		if(a[mid]==key)
		return mid;
		else if(a[mid]>key)
		right=mid-1;
		else left=mid+1;
	}
	return -1;
} 
int main()
{
	int i,n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	for(int i=0;i<n;i++)
	{
		int pos=bin(0,n-1,m-a[i]);
		if(pos!=-1&&i!=pos)
		{
			printf("%d %d\n",a[i],a[pos]);
			break;
		}
	}
	if(i==n)
	printf("No Solution\n");
	return 0;
}

③two pointers

先使用sort函数排序,定义i=0,j=n-1,并根据a[i]+a[j]和M的大小来进行操作(整体过程是i和j的相遇过程)

1.a[i]+a[j]==M 则找到一组方案退出循环

2.a[i]+a[j]<M  则令i+1

3.a[i]+a[j]>M  则令j-1

直到i>=j 或满足条件a时结束,结束时根据i>=j是否成立来确定解是否存在

//solution3:two pointers
const int maxn=100010;
int a[maxn];
void twopointers(int n,int m)
{
	int i=0,j=n-1;
	while(i<j)
	{
		if(a[i]+a[j]==m)
		break;
		else if(a[i]+a[j]<m)
		{
			i++;
		}
		else
		{
			j--;
		}
	}
	if(i<j)
	{
		printf("%d %d\n",a[i],a[j]);
	}
	else
	{
		printf("No Solution\n");
	}
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	twopointers(n,m);
	return 0;
}

 

【资源介绍】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业毕设项目,也可以作为小白实战演练初期项目立项演示的重要参考借鉴资料。 3、本资源作为“学习资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研调试实践。 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip 图像数据处理工具+数据(帮助用户快速划分数据集并增强图像数据集。通过自动化数据处理流程,简化了深度学习项目的数据准备工作).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值