目录
刷题集训 A
Day 1 成绩分析
题目描述
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
请计算这次考试的最高分、最低分和平均分。
输入描述
输入的第一行包含一个整数 n (1≤n≤104),表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
输出描述
输出三行。
第一行包含一个整数,表示最高分。
第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int a[n];
double sum=0;
for(int i=0; i<n; i++) {
cin>>a[i];
}
for(int i=0; i<n; i++) {
sum+=a[i];
}
sort(a,a+n);
cout<<a[n-1]<<endl;
cout<<a[0]<<endl;
float avg=sum/n;
printf("%.2lf",avg);
return 0;
}
Day 1 饮料换购
题目描述
乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊 C 型饮料,凭 3 个瓶盖可以再换一瓶 C 型饮料,并且可以一直循环下去(但不允许暂借或赊账)。
请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的 n 瓶饮料,最后他一共能喝到多少瓶饮料。
输入描述
输入一个整数 n(0<n<1000),表示开始购买的饮料数量。
输出描述
输出一个整数,表示实际得到的饮料数
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int sum=n;
while(n>=3){
int yu=n%3;
int shang = n/3;
sum+=shang;
n=yu+shang;
}
cout<<sum<<endl;
return 0;
}
刷题集训 B
Day 1 分巧克力
题目描述
儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。为了公平起见,
小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:
-
形状是正方形,边长是整数;
-
大小相同;
例如一块 6x5 的巧克力可以切出 6 块 2x2 的巧克力或者 2 块 3x3 的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
输入描述
第一行包含两个整数 N,K。
以下 N 行每行包含两个整数 Hi,Wi 。
输入保证每位小朋友至少能获得一块 1x1 的巧克力。
输出描述
输出切出的正方形巧克力最大可能的边长。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int w[maxn], h[maxn];
int n,k;
int Enum(int l, int r){ //枚举边长为1到上限
int low=l, high=r;
while(low<=high){
int mid=(low+high)/2; //当前枚举的边长
int cnt=0;
for(int i=0; i<n; i++){
cnt+=(w[i]/mid)*(h[i]/mid);
if(cnt>=k) break;
}
if(cnt>=k){
low=mid+1;
}
else{
high=mid-1;
}
}
return low-1;
}
int main(){
cin>>n>>k;
int res=0;
for(int i=0; i<n; i++){
cin>>w[i]>>h[i];
res=max(res, min(w[i],h[i])); //找到所有巧克力中较小边的最大值,作为枚举上限
}
cout<<Enum(1,res);
return 0;
}
Day 1 递增三元组
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(){
long long n;
cin>>n;
long long a[n],b[n],c[n];
for(int i=0; i<n; i++){
cin>>a[i];
}
sort(a,a+n);//从小到大
for(int i=0; i<n; i++){
cin>>b[i];
}
sort(b,b+n);
for(int i=0; i<n; i++){
cin>>c[i];
}
sort(c,c+n);
//
LL res=0, l=0, r=0;
for(int i=0;i<n;i++)
{
while(a[l]<b[i]&&l<n) l++;//l停止时,a[l]等于或大于b[i]
while(c[r]<=b[i]&&r<n) r++;//r停止时,c[r]大于b[i]
res+=(LL)l*(n-r);
}
cout<<res<<endl;
return 0;
}
Day 1 小明的衣服
题目描述
小明买了 n 件白色的衣服,他觉得所有衣服都是一种颜色太单调,希望对这些衣服进行染色,每次染色时,他会将某种颜色的所有衣服寄去染色厂,第 i 件衣服的邮费为ai 元,染色厂会按照小明的要求将其中一部分衣服染成同一种任意的颜色,之后将衣服寄给小明, 请问小明要将 n 件衣服染成不同颜色的最小代价是多少?
输入描述
第一行为一个整数 n ,表示衣服的数量。
第二行包括 n 个整数a1,a2...an 表示第 i 件衣服的邮费为ai 元。
输出描述
输出一个整数表示小明所要花费的最小代价。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans;
// 1、每次染一件路费最贵的。
// 2、每次染除了最贵那件其他的。
// 二者结果一样,可用优先队列实现,
// 每次取最大的两个,出队,将二者和入队,
// 相当于每次取最大的和再加上之前算出的和。
// 过程相当于每次摘走最大的,累和。
int main(){
int n;
cin>>n;
//定义一个优先队列 并排序 greater是升序小堆栈 less是降序
priority_queue<ll, vector<ll>, greater<ll>> q;
for(int i=0; i<n; i++){
ll x;
cin>>x;
//push() 表示将元素插到队尾
q.push(x);
}
//取了n-1次
while(q.size()>1){
ll a=q.top(); q.pop();
ll b=q.top(); q.pop();
ll c=a+b;
ans+=c;
q.push(c);
}
cout<<ans<<endl;
return 0;
}
刷题集训 C
Day 1 数字三角形
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int n, a[N][N], dp[N][N];
signed main(){
memset(dp, -0x3f, sizeof(dp));
cin>>n;
for(int i=1; i<=n; i++){
for(int j=1; j<=i; j++){
cin>>a[i][j];
}
}
dp[1][1]=a[1][1];
for(int i=2; i<=n; i++){
for(int j=1; j<=i; j++){
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
}
}
if((n-1)&1) cout<<max(dp[n][1+(n-1)/2],dp[n][1+(n-1)/2+1])<<'\n';
else cout<<dp[n][1+(n-1)/2]<<'\n';
return 0;
}
Day 1 跳跃
题目描述
小蓝在一个n 行 m 列的方格图中玩一个游戏。
开始时,小蓝站在方格图的左上角,即第 1 行第 1 列。
小蓝可以在方格图上走动,走动时,如果当前在第r 行第 c 列,他不能走到行号比 r 小的行,也不能走到列号比 c 小的列。同时,他一步走的直线距离不超过 3。
例如,如果当前小蓝在第 3 行第 5 列,他下一步可以走到第 3 行第 6 列、第 3 行第 7 列、第 3 行第 8 列、第 4 行第 5 列、第 4 行第6 列、第 4 行第 7 列、第 5 行第 5 列、第 5 行第 6 列、第 6 行第 5 列之一。
小蓝最终要走到第 n 行第 m 列。
在图中,有的位置有奖励,走上去即可获得,有的位置有惩罚,走上去就要接受惩罚。奖励和惩罚最终抽象成一个权值,奖励为正,惩罚为负。
小蓝希望,从第 1行第 1 列走到第 n 行第m 列后,总的权值和最大。请问最大是多少?
#include<bits/stdc++.h>
using namespace std;
int dir[9][2]={{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{2,0},{2,1},{3,0}};
int n,m;
int M[102][102];
int dp[102][102];
int ans=-99999;
void dfs(int x, int y, int sum){
dp[x][y]=1;
//起始点sum
if(sum<=ans) return;
//一行一列
if(x==n&&y==m){
ans=sum;
}else{
for(int i=0;i<9;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=1&&xx<=n&&yy<=m&&dp[xx][yy]==0){
dfs(xx,yy,sum+M[xx][yy]);
dp[xx][yy]=0;
}
}
}
}
int main(){
memset(dp, 0, sizeof(dp));
cin>>n>>m;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
cin>>M[i][j];
}
}
dfs(1,1,M[1][1]);
cout<<ans<<endl;
return 0;
}
Day 1 蓝太子序列
题目描述
L 星球上的生物由蛋蓝质组成,每一种蛋蓝质由一类称为蓝肽的物资首尾连接成一条长链后折叠而成。
生物学家小乔正在研究 L 星球上的蛋蓝质。她拿到两个蛋蓝质的蓝肽序列,想通过这两条蓝肽序列的共同特点来分析两种蛋蓝质的相似性。
具体的,一个蓝肽可以使用 1 至 5 个英文字母表示,其中第一个字母大写,后面的字母小写。一个蛋蓝质的蓝肽序列可以用蓝肽的表示顺序拼接而成。
在一条蓝肽序列中,如果选取其中的一些位置,把这些位置的蓝肽取出,并按照它们在原序列中的位置摆放,则称为这条蓝肽的一个子序列。蓝肽的子序列不一定在原序列中是连续的,中间可能间隔着一些未被取出的蓝肽。
如果第一条蓝肽序列可以取出一个子序列与第二条蓝肽序列中取出的某个子序列相等,则称为一个公共蓝肽子序列。
给定两条蓝肽序列,找出他们最长的那个公共蓝肽子序列的长度。
#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005];
string s1, s2;//要输入的两个序列
string str1[1005], str2[1005];//记录两个序列的所有子序列
int cnt1, cnt2;
int main(){
cin>>s1>>s2;
int d1=s1.length(), d2=s2.length();
//子序列首字母大写,后几位全小写
for(int i=0; i<d1;)
{
cnt1++;
if(s1[i]>='A'&&s1[i]<='Z'){
str1[cnt1]+=s1[i++];
while(s1[i]>='a'&&s1[i]<='z'){
str1[cnt1]+=s1[i++];
}
}
}
//
for (int i = 0; i < d2;)
{
cnt2++;
if (s2[i] >= 'A' && s2[i] <= 'Z')
{
str2[cnt2] += s2[i++];
while (s2[i] >= 'a' && s2[i] <= 'z')
{
str2[cnt2] += s2[i++];
}
}
}
//遍历
for (int i = 1; i <= cnt1; i++)//遍历所有子序列
for (int j = 1; j <= cnt2; j++)
{
if (str1[i] == str2[j]) dp[i][j] = dp[i - 1][j - 1] + 1;//这里上文已解释过
else dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
cout << dp[cnt1 ][cnt2 ] << endl;
return 0;
}