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; }