3331-3340(十题)

3331:【例56.2】 购买饮料

【题目描述】

小 B 出门游玩,他现在走到了 nn家饮品店前,第ii家买饮料的花费为 costicosti,他只能去花费不超过自己所带钱数额的店,但他现在不确定自己兜里有多少钱,所以现在给出 mm 次询问,请问如果他有 aiai元,他有几家饮品店可选?

【输入】

第一行两个整数分别表示 nn,mm。

第二行 nn 个整数,第 ii 个表示 costicosti,接下来 mm 行,每行一个整数表示询问。1≤n,m,costi≤1061≤n,m,costi≤106 ,1≤ai≤1091≤ai≤109。

【输出】

对于每次询问回答小 BB 有几家饮品店可选。

【输入样例】

5 2
1 2 3 4 5
3
5

【输出样例】

3
5

源代码:

#include <bits/stdc++.h>
using namespace std;
int x,n,m,a[1000000+10];
int main()
{
	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<m;i++)
	{
		scanf("%d",&x);
		printf("%d\n",upper_bound(a,a+n,x)-a);
	}
	return 0;
}

3332:练56.1 猜猜乐

【题目描述】

格莱尔和尼克玩猜数游戏。格莱尔默默选定一个数(1 ~ 100之间的整数),尼克每次猜一个数,格莱尔会告诉尼克他是猜大了还是猜小了,或是猜对了。尼克采用二分法猜数,请你模拟尼克猜数的过程。

【输入】

一行一个整数,为n。

【输出】

输出若干行,每行一个整数,为此时二分得到的数,当二分得到的数为n时,输出“成功!”,否则当二分结束时,输出“失败!”。

【输入样例】

56

【输出样例】

50
75
62
56
成功!

源代码:

#include<iostream>
using namespace std;
int search(int b[],int len,int key)
{
	int high,low;
	high=len-1;
	low=0;
	int mid;
	
	mid=len/2;
	while(high>=low)
	{
		mid=(high+low)/2;
		//cout<<"mid="<<mid<<" "<<b[mid]<<endl;
		cout<<mid+1<<endl;
	
		if(b[mid]==key)
	  		return mid;
		else if(b[mid]>key)
	       		high=mid-1;         
	     	else 
	       		low=mid+1;
	}
	return 0;
}
main()
{
	const int max=100;
	int a[max],n;
  
	for(int i=0;i<max;i++)
    	a[i]=i+1;
  
  	do
  	{
    	cin>>n;	
  	}while(n<1||n>100);
  
  	if(search(a,max,n)) 
    	cout<<"成功!";
  	else
    	cout<<"失败!";
	return 0; 
}

3333:练56.2 查找最接近的元素


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 1141     通过数: 460

【题目描述】

在一个非降序列中,查找与给定值最接近的元素。

【输入】

第一行包含一个整数nn,为非降序列长度。1≤n≤1000001≤n≤100000。

第二行包含nn个整数,为非降序列各元素。所有元素的大小均在0∼1,000,000,0000∼1,000,000,000之间。第三行包含一个整数mm,为要询问的给定值个数。1≤m≤100001≤m≤10000。

接下来mm行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0∼1,000,000,0000∼1,000,000,000之间。

【输出】

mm 行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。

【输入样例】

3
2 5 8
2
10
5

【输出样例】

8
5

源代码:

#include <bits/stdc++.h>
using namespace std;
 

 
int n,m,a[100005],b,l,r,mid;
bool flag;
 
int main() 
{
	a[0]=2147483647;
	
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
		
	cin>>m;
	
	for(int i=1;i<=m;i++)
	{
		cin>>b;
		l=1,r=n;
		flag=1;
		
		while(l<=r)
		{
			mid=(l+r)/2;
			
			if(a[mid]==b)
			{
				cout<<b<<endl;
				flag=0;
				break;
			}
			
			if(b>a[mid])
			{
				l=mid+1;
			}
			
			else
				r=mid-1;
		}
		
		if(flag)
		{
			if(abs(b-a[r])<=abs(a[l]-b))
			{
				cout<<a[r]<<endl;
			}
			
			else
			{
				cout<<a[l]<<endl;
			}
		}
	}
	
	return 0;
}

3334:【例57.1】 字典序第几小


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 766     通过数: 562

【题目描述】

从11开始到nn(1≤n≤91≤n≤9)这nn个数字一共可以组成n!n!个不同的排列。现在给出其中一个排列,求它是所有排列中字典序第几小的排列?

【输入】

第一行一个整数 nn。

第二行一个整数 xx,是由 11 到 nn 这 nn 个数字组成的某个排列。

【输出】

一个整数,表示该排列是字典序第几小的。

【输入样例】

4
2143

【输出样例】

8

源代码:

#include <bits/stdc++.h>
using namespace std;
int n,cnt;
char ch;
vector<int> a,b;
int main()
{
 
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>ch;
		b.push_back(ch-48);
		a.push_back(i);
	}
	do
	{
		cnt++;
		if(a==b)
		{
			break;
		}
	}while( next_permutation(a.begin(),a.end()));
	
	cout<<cnt<<endl;
	
	return 0;
}

3335:【例57.2】 上一个排列


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 734     通过数: 492

【题目描述】

地球人都知道,从 11 开始到 nn (1≤n≤91≤n≤9) 这 nn 个数字一共可以组成 n!n! 个不同的排列。现在把这 nn 个排列按字典序从小到大排序,给出其中一个排列,求该排列的上一个排列。

【输入】

第一行一个整数 nn,表示排列的长度。

第二行 nn 个用空格分隔的整数,为 11 到 nn 组成的某个排列。

【输出】

如果上一个排列存在,则输出;否则输出"ERROR"

【输入样例】

4
2 1 3 4

【输出样例】

1 4 3 2

源代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n,a[15];
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	if(prev_permutation(a+1,a+n+1))
		for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	else cout<<"ERROR";
	return 0;
}

3336:【例57.3】火星人


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 693     通过数: 511

【题目描述】

人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。

火星人用一种非常简单的方式来表示数字——掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为11,22,33……。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。

一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指——拇指、食指、中指、无名指和小指分别编号为11,22,33,44和55,当它们按正常顺序排列时,形成了55位数1234512345,当你交换无名指和小指的位置时,会形成55位数1235412354,当你把五个手指的顺序完全颠倒时,会形成5432154321,在所有能够形成的120120个55位数中,1234512345最小,它表示11;1235412354第二小,它表示22;5432154321最大,它表示120120。下表展示了只有33根手指时能够形成的66个33位数和它们代表的数字:

三进制数123132213231312321123132213231312321代表数字123456123456

现在你有幸成为了第一个和火星人交流的地球人。一个火星人会让你看他的手指,科学家会告诉你要加上去的很小的数。你的任务是,把火星人用手指表示的数与科学家告诉你的数相加,并根据相加的结果改变火星人手指的排列顺序。输入数据保证这个结果不会超出火星人手指能表示的范围。

【输入】

三行,第一行有一个正整数NN,表示火星人手指的数目(1≤N≤100001≤N≤10000)。第二行是一个正整数MM,表示要加上去的小整数(1≤M≤1001≤M≤100)。下一行是11到NN这NN个整数的一个排列,用空格隔开,表示火星人手指的排列顺序。

【输出】

只有一行,这一行含有NN个整数,表示改变后的火星人手指的排列顺序。每两个相邻的数中间用一个空格分开,不能有多余的空格。

【输入样例】

5
3
1 2 3 4 5

【输出样例】

1 2 4 5 3

源代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a[10005];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++) next_permutation(a+1,a+n+1);
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
}

3337:练57.1 全排列问题


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 1162     通过数: 479

【题目描述】

输出自然数 11 到 nn 所有不重复的排列,即 nn 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

【输入】

一个整数nn (1≤n≤91≤n≤9)。

【输出】

由1∼n1∼n 组成的所有不重复的数字序列,每行一个序列。每个数字保留 55 个场宽。

【输入样例】

3

【输出样例】

1    2    3
1    3    2
2    1    3
2    3    1
3    1    2

源代码:

#include <bits/stdc++.h>
using namespace std;
int a[10],n;
int main( void )
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		a[i]=i;
	}
	
	do{
		for(int i=1;i<=n;i++)
		{
			printf("%5d",a[i]);
		}
		puts("");
	}while(next_permutation(a+1,a+n+1));
	
	return 0;
}

3338:【例58.1】 明明的随机数


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 1170     通过数: 819

【题目描述】

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 NN 个 11 到 10001000 之间的随机整数(N≤100N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

【输入】

输入有2行,第11行为11个正整数,表示所生成的随机数个数:NN。

第2行有NN个用空格隔开的正整数,为所产生的随机数。

【输出】

输出 22 行,第 11 行为 11 个正整数 MM,表示不相同的随机数的个数。

第 22 行为 MM 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

【输入样例】

10
20 40 32 67 40 20 89 300 400 15

【输出样例】

8
15 20 32 40 67 89 300 400

源代码:

#include <bits/stdc++.h>
using namespace std;
int main( )
{
	int n,a[105],b[105],temp=0;
	int k;
	cin>>n;
	temp=n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	
	 
	for(int i=1;i<temp;i++)
	{
		for(int j=i+1;j<=temp;j++)
		{
			k=i;
			if(a[k]>a[j])  k=j;
			
			swap(a[i],a[k]);	
		}
	}
	
	 
	for(int i=1;i<temp;i++)
	{
		if(a[i]==a[i+1])
		{
			a[i]=0;
			n--;	
		}
	}
	cout<<n<<endl;
	for(int i=1;i<=temp;i++)
	{
		if(a[i])  cout<<a[i]<<' ';
	}
	
	return 0;
}

3339:【例58.2】 序列处理


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 1022     通过数: 590

【题目描述】

给出一个含有 nn 个整数的序列,请你输出它们的总和、最大值、最小值、并大到小输出(去重后)。

【输入】

第—个整数nn (1<n≤1041<n≤104)

第二行nn个整数aiai (1≤ai≤1041≤ai≤104)。

【输出】

第一行输出一个整数,表示总和。

第二行输出一个整数,表示最大值。

第三行输出一个整数,表示最小值。

第四行输出若干个空格分隔的整数,表示从大到小排序后的序列(相同的数只输出一次)。

【输入样例】

8
8 5 1 9 2 6 2 6

【输出样例】

39
9
1
9 8 6 5 2 1

源代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
	long long a1=0,a2=10000,a3=0;
	int n,a[10005],t;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]>a1) a1=a[i];
		if(a[i]<a2) a2=a[i];
		a3+=a[i];
	}
	cout<<a3<<endl;
	cout<<a1<<endl;
	cout<<a2<<endl;
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			if(a[i]<a[j]){
				t=a[i];
				a[i]=a[j];
				a[j]=t;
			}
			if(a[i]==a[j]&&i!=j) a[j]=-1;
		}
	}
	for(int i=1;i<=n;i++){
		if(a[i]>=0)cout<<a[i]<<" ";
	}
	return 0;
}

3340:【例58.3】 电梯运行时间


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 1457     通过数: 558

【题目描述】

电梯每向上运行一层需要 66 秒钟,向下运行一层需要 44 秒钟,每开门一次需要 55 秒(如果有人到达才开门),并且每下一个人需要加 11秒。

特别指出,电梯最开始在 00 层,并且最后必须再回到 00 层才算一趟任务结束。假设在开始的时候已知电梯内的每个人要去的楼层,你能计算出完成本趟任务需要的总时间吗?

【输入】

第一行,一个正整数nn(1<n<1051<n<105),表示乘坐电梯的人数。

第二行,nn个正整数,aiai (1<ai<1071<ai<107)表示第i个人要去的楼层。

【输出】

仅一行,一个正整数,表示完成这趟任务需要的时间。

【输入样例】

4
3 7 3 1

【输出样例】

89

源代码:

#include <bits/stdc++.h>
using namespace std;
long long a[1000000+10];
int main( )
{
	long long n,i;
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>a[i];
	}
	sort(a,a+n);
	
	long long time=a[i-1]*10;
	time+=(unique(a,a+n)-a)*5;
	time+=n;
	cout<<time;
	return 0;
}
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值