书架
为了方便同学们查阅资料,程序设计兴趣小组的辅导老师打算将积攒了很多年的n本书放到上课教室的书架上去。
教室的书架是一层一层叠起来的,每一层最多可以放m本书。每一层的高度由放在这层中最高的那本书决定的,如果不放书,则认为这层的高度为0。为了使每个同学能方便地拿到想要的书,书架的总高度应尽可能低。请编程计算将这n本书放在书架上后书架的最小总高度,计算的过程中不考虑书的厚度与书架本身材料的厚度。
输入格式
输入共n+1行。
第1行2个整数n和m (1≤m≤n≤100000) 。
接下来n行,每行1个正整数,分别表示每本书的高度(每本书的高度不超过100)。
输出格式
输出共1行,表示将n本书放入书架后书架的最小总高度。
输入/输出例子1
输入:
3 2
20 10 30
输出:
40
样例解释
将高度是30和20的两本书放在一层,则这层的高度为30,将高度是10的那本书放在另外一层,则这层的高度为10,则书架的总高度为40,满足最小。
代码:
#include<bits/stdc++.h>
using namespace std;
bool cmp(int x,int y)
{
return x>y;
}
int n,m,a[1000005],s;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i+=m)
s+=a[i];
cout<<s;
return 0;
}
礼物
国庆马上要到了。小明喜欢的礼物有n种分别是:公仔、电子手表、漫画书等。
每种礼物有一件,每种礼物价钱都不一样。小明手头上有 m 元。
小明最多可以买多少件礼物?
输入格式
第一行,两个整数:n,m 1 <= n<=100,1<=m<= 100000。
第二行,n个空格分开的整数(每个整数<=1000),代表每种礼物的价钱。
输出格式
一个整数,小明能买多少件礼物。
输入/输出例子1
输入:
3 100
40 70 50
输出:
2
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,a[1000005],ans,s;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
ans+=a[i];
if(ans>m)break;
else s++;
}
cout<<s;
return 0;
}
数字圈
当我们写数字时会发现有些数字有封闭区域, 有的数字没有封闭区域。 数字 0 有一个封闭区域, 数字 1、 2、3 都没有封闭区域, 数字 4 有一个封闭区域, 数字 5 没有封闭区域, 数字 6 有一个封闭区域, 数字 7 没有
封闭区域, 数字 8 有两个封闭区域, 数字 9 有一个封闭区域。
现在你要构造一个最小的非负整数, 使得它的各位数字的封闭区域的数量加起来的总和恰好等于 K。
输入格式
一个整数 K。 1 <= K <= 2500。
输出格
满足题意的最小的非负整数。
输入/输出例子1
输入:
1
输出:
0
输入/输出例子2
输入:
2
输出:
8
输入/输出例子3
输入:
40
输出:
88888888888888888888
代码:
#include<bits/stdc++.h>
using namespace std;
int k;
int main(){
cin>>k;
if(k%2==0)
{
for(int i=0;i<k/2;i++)
cout<<8;
return 0;
}
if(k%2==1&&k!=1)
{
cout<<4;
for(int i=0;i<k/2;i++)
cout<<8;
return 0;
}
if(k==1)cout<<0;
return 0;
}
危险的实验
小明最近在上化学课,他需要使用到 n 种化学物质来进行他的实验。在做实验的时候, 他需要将所有化学物质放在桌面上,按次序排成一条直线。
然而每一种化学物质都是危险品,对于第 i个化学物质,如果有另外一个化学物质距离它的距离小于ai,那么就会发生爆炸。
小明想知道如果要安全的完成他的实验,桌子最短可以多短。
输入格式
第一行一个整数n,表示化学物质的个数。
第二行有n个整数,第i个整数ai表示第i个化学物质必须与其他化学物质保持的距离。
输出格式
输出一行,包括一个整数,表示能够让小明安全完成实验的桌子最小长度。
注意:物品要安原来的次序摆放。
输入/输出例子1
输入:
3
3 1 2
输出:
5
数据范围
20%的数据,1<=n<=20 ;
50%的数据,1<=n<=100000 ;
100%的数据,1<=n<=1000000,1<=ai<=100000。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[1000005],s,t;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<n;i++)
{
t=max(a[i],a[i+1]);
s+=t;
}
cout<<s;
return 0;
}
最大步数
给出了两个非负整数 P 和 Q。您的任务是使得 P 和 Q 相等。在每一步中,您可以执行以下两项操作之一:
1、将任何质数加到 P 上。
2、从 Q 减去任何质数。
如果不可能使 P 和 Q 相等,则输出-1。否则,输出一个非负整数:可以执行的最大步数。
输入格式
一行,两个整数 P 和 Q。 0 <= P,Q <= 10^18
输出格式
一个整数。
输入/输出例子1
输入:
5 9
输出:
2
输入/输出例子2
输入:
5 10
输出:
2
输入/输出例子3
输入:
5 6
输出:
-1
提示
数字0和1不是质数
代码:
#include<bits/stdc++.h>
using namespace std;
long long p,q;
int main()
{
cin>>p>>q;
if(p>q){cout<<-1;return 0;}
if(p-q==0){cout<<0;return 0;}
if(p-q==1){cout<<-1;return 0;}
cout<<(q-p)/2;
return 0;
}
渡河
总共有 X 人要坐船过河。
一个小船最多可以坐 4 人,一个小船固定收费 32 元。
一个大船最多可以坐 6 人,一个大船固定收费 36 元。
码头有无穷多小船和大船。
问如何坐船,才能使得总费用最小。
输入格式
一个整数 X。
60%的数据, 1 <= X <= 1000
80%的数据,1 <= X <= 1000000
100 的数据,1 <= X <= 2000000000
输出格式
一个整数,表示最小的总费用。
输入/输出例子1
输入:
4
输出:
32
输入/输出例子2
输入:
12
输出:
72
代码:
#include<bits/stdc++.h>
using namespace std;
long long x,s,l;
int main()
{
cin>>x;
if(x<=4)s=32;
else
{
s+=(x/6)*36;
l=x%6;
if(l==5)s+=36;
if(l==4||l==3)s+=32;
if(l==2||l==1)s+=28;
}
cout<<s;
return 0;
}
越野跑
为了能在下一次跑步比赛中有好的发挥,桐桐在一条山路上开始了她的训练 。桐桐希望能在每次训练中跑得尽可能远,不过她也知道农场中的一条规定:独自进山的时间不得超过M秒(1 <= M <= 10,000,000)。
整条山路被桐桐划分成T个长度相同的小段(1 <= T <= 100,000),用S_i表示第i个小段的路况。S_i为U,F,D这3个字母之一,它们分别表示第i个小段是上坡、平地,或是下坡。
桐桐要花U秒(1 <= U <= 100)才能跑完一段上坡路,跑完一段平地的耗时是F秒(1 <= F <= 100),跑完一段下坡路要花D秒(1 <= D <= 100)。注意,沿山路原路返回的时候,原本是上坡路的路段变成了下坡路,原本是下坡路的路段变成了上坡路。
桐桐想知道,在能按时返回农场的前提下,她最多能在这条山路上跑多远。
输入格式
第1行: 5个用空格隔开的整数:M,T,U,F,D。
第2..T+1行: 第i+1行为1个字母S_i,描述了第i段山路的路况。
输出格式
输出1个整数,为桐桐在按时回到农场的前提下,最多能跑到多远。
输入/输出例子1
输入:
13 5 3 2 1
ufudf
输出:
3
样例解释
桐桐跑步的最大耗时为13秒(这么短...),她跑步的山路一共被划成5段。桐桐跑完一段上坡路的耗时为3秒,平地为2秒,下坡路为1秒。山路各段的走向如下图所示:
桐桐跑完山路的前3段,然后返回,总耗时为3 + 2 + 3 + 1 + 2 + 1 = 12秒,只比她能在外面呆的时限少1秒。如果她跑得更远,就无法按时回到农场
代码:
#include<bits/stdc++.h>
using namespace std;
int m,t,u,f,d,ans,o,i;
string s;
int main(){
cin>>m>>t>>u>>f>>d>>s;
while(1)
{
if(s[i+1]=='u'||s[i+1]=='d')ans=(u+d);
else ans=f*2;
if(o+ans>m||i==s.size())break;
if(s[i]=='u'||s[i]=='d')o+=(u+d);
else o+=f*2;
i++;
}
cout<<i;
return 0;
}
逃生
迷宫被分成N行M列的格子。从上往下看,行的编号是1至N。从左往右看,列的编号是1至M。你现在位于第1行第1列格子,迷宫的出口在第N行第M列的格子。每进入一个格子都要消耗能量。迷宫格子的能量有点奇特,同一行格子消耗的能量是相等的,第1行的每一个格子消耗的能量都是E[1],第2行的每一个格子消耗的能量都是E[2],....第N行的每一个格子消耗的能量都是E[N]。现在你要从左上角格子走到右下角格子,每一步可以从当前格子走到相邻的上、下、左、右四个格子之一,你的目标是消耗最小的总能量。注意:左上角格子和右下角格子消耗的能量也要算。
输入格式
第一行,M和N。
接下来有N个数,第i个是E[i]。
输出格式
一个整数。
输入/输出例子1
输入:
5 6
3 2 5 4 2 8
输出:
32
输入/输出例子2
输入:
3 3
1 2 1
输出:
6
输入/输出例子3
输入:
4 4
3 2 4 2
输出:
17
数据范围
1<=N<=50,1<=M<=1000000000。注意:M表示列,N表示行。
1<=E[i]<=1000。
代码:
#include<bits/stdc++.h>
using namespace std;
long long x,n,sum,m,minn=10000;
int main(){
cin>>m>>n;
for(int i=0;i<n;i++)
{
cin>>x;
sum+=x;
minn=min(minn,x);
}
cout<<sum+minn*(m-1);
return 0;
}
二零二零
给出一个字符串S,其中满足S的每一个字符都是数字字符,你要删除S的连续一段字符(也可以删除0个字符),使得剩下的字符依次连接起来的字符串是“2020”,可以做到吗?如果可以做到输出“YES”,否则输出“NO”。
输入格式
第一行,一个整数G,表示有G组测试测试。1<=G<=10。
每组测试格式如下:
第一行,一个整数n,表示字符串S的长度。1<=n<=200。
第二行,字符串S。
输出格式
共G行,每行一个字符串,“YES”或“NO”,双引号不用输出。
输入/输出例子1
输入:
5
8
20192020
8
22019020
4
2020
5
20002
6
729040
输出:
YES
YES
YES
NO
NO
代码:
#include<bits/stdc++.h>
using namespace std;
int g,n;
string s;
bool jjj(string s)
{
int len=s.size();
if(s[0]=='2'&&s[len-3]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
if(s[0]=='2'&&s[1]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[len-1]=='0')return true;
if(s[len-4]=='2'&&s[len-3]=='0'&&s[len-2]=='2'&&s[len-1]=='0')return true;
if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[3]=='0')return true;
return false;
}
int main()
{
cin>>g;
while(g--)
{
cin>>n;
cin>>s;
if(jjj(s)==true)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
学生分组
有N组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界R和下界L(L<=R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使N组学生的人数都在[L,R]中。
输入格式
第一行一个整数N,表示学生组数;1<=N<=100
第二行N个整数K,表示每组的学生个数;1<=K<=100
第三行两个整数 L,R,表示下界和上界。
输出格式
一个数,表示最少的交换次数,如果不能满足题目条件输出-1
输入/输出例子1
输入:
4
10 20 30 40
18 28
输出:
14
代码:
#include<bits/stdc++.h>
using namespace std;
int n,l,r;
int a[100009];
int s,h;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
s+=a[i];
}
cin>>l>>r;
int s1,s2;
if(s<l*n||s>r*n)
{
cout<<"-1";
return 0;
}
else
{
for(int i=0;i<n;i++)
{
if(a[i]<l)s1+=l-a[i];
if(a[i]>r)s2+=a[i]-r;
}
}
cout<<max(s1,s2)<<endl;
return 0;
}
回文数列
czm非常喜欢回文数列。回文数列是指一个包含N个整数的数列A,分别为A[1],A[2],……,A[n],对于第i(1<=i<=N)个数A[i],都有A[i]=A[N-i+1]。但是回文数字非常难得到。
现在czm想到了一个办法,他可以将数列中,任意两个相邻的数字合并,用它们的和来代替,合并完成的值还可以和其他值不断合并,直到只剩下一个数。要知道一个数肯定是回文数列。
当然,czm希望他的回文数列尽可能长,因此,请你帮助czm计算一下,对于一个长度为N的数列,经过最少多少次合并,可以构成一个回文数列。
输入格式
第一行一个整数N(1<=N<=500000),表示数列中整数的个数。
第二行包含N个正整数,中间用空格分开,表示数列中的数字。
输出格式
输出一个最小合并次数,使得数列变成回文数列。
输入/输出例子1
输入:
3
1 2 3
输出:
1
输入/输出例子2
输入:
5
1 2 4 6 1
输出:
1
输入/输出例子3
输入:
4
1 4 3 2
输出:
2
代码:
#include<bits/stdc++.h>
using namespace std;
long long a[1000005],n,ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1,j=n;i<j;)
{
if(a[i]==a[j])i++,j--;
else if(a[i]>a[j])a[j-1]+=a[j],j--,ans++;
else if(a[i]<a[j])a[i+1]+=a[i],i++,ans++;
}
cout<<ans;
return 0;
}
均分纸牌
有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。
移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如 N=4,4 堆纸牌数分别为: ① 9 ② 8 ③ 17 ④ 6 移动3次可达到目的: 从 ③ 取 4 张牌放到 ④ (9 8 13 10) -> 从 ③ 取 3 张牌放到 ②(9 11 10 10)-> 从 ② 取 1 张牌放到①(10 10 10 10)。
输入格式
第一行N。第二行A1 A2 … An (每堆纸牌初始数)
输出格式
所有堆均达到相等时的最少移动次数。 (1 <= N <= 100,l<= Ai <=10000 )
输入/输出例子1
输入:
4
9 8 17 6
输出:
3
代码:
#include<bits/stdc++.h>
using namespace std;
int num[105],n,ave,tot,ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>num[i];
tot+=num[i];
}
ave=tot/n;
for(int i=1;i<=n;i++)
num[i]-=ave;
for(int i=1;i<n;i++)
{
if(num[i]==0) continue;
num[i+1]+=num[i];
ans++;
}
cout<<ans;
return 0;
}
叠罗汉
农场的N头奶牛喜欢玩叠罗汉游戏,就是几头奶牛1头奶牛接着1头奶牛的站成一柱子形状。不过奶牛的力量不一样,用数值Ci表示第i头奶牛它的上面最多可以站多少头奶牛,问这些奶牛最少可以站成几个柱子形状。
输入格式
第一行1个整数N,表示有多少头奶牛。1<=N<=1000。
第二行N个正整数Ci,表示这些奶牛的力量。0<=Ci<=1000。
输出格式
一个整数,表示最少成几个“罗汉”。
输入/输出例子1
输入:
5
0 2 1 2 2
输出:
2
样例解释
可以第1、第3、第2头奶牛从上向下叠罗汉;
第4、第5头奶牛叠罗汉。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,f,ans,c[1005],k,d;
int main(){
cin>>n;
for (int i=0;i<n;i++)
{
cin>>f;
c[f]++;
}
while(k<n)
{
d=0;
ans++;
for(int i=0;i<1000;)
{
if(c[i]!=0&&i>=d)
{
c[i]--;
k++;
d++;
}
else i++;
}
}
cout<<ans;
return 0;
}
菜鸟整理的一些题,大佬不喜勿喷......