牛客寒假算法基础集训营6
A 出题
链接:https://ac.nowcoder.com/acm/contest/332/A
来源:牛客网
题目描述
小B准备出模拟赛。
她把题目按难度分为四等,分值分别为6,7,8,9。
已知小B共出了m道题,共n分。
求小B最少出了多少道6分题。
她把题目按难度分为四等,分值分别为6,7,8,9。
已知小B共出了m道题,共n分。
求小B最少出了多少道6分题。
输入描述:
两个正整数n,m
输出描述:
一个整数表示答案
无解输出 jgzjgzjgz
思路:
这题写很好写,但是思路确实有点难想
首先确定是否无解 即分数不在全出6分题,和全出9分题之间
然后就将这些题默认为9分题,看离分数还差多少,然后减就行了
代码:
#include <bits/stdc++.h> using namespace std; long long n,m; int main(){ cin>>n>>m; if(n<6*m||n>9*m) cout<<"jgzjgzjgz"<<endl; else { long long t=m*9-n; if(2*m>=t) cout<<0<<endl; else { t-=2*m; cout<<t<<endl; } } return 0; }
B 煤气灶
链接:https://ac.nowcoder.com/acm/contest/332/B
来源:牛客网
目描述
小j开始打工,准备赚钱买煤气灶。
第一天,小j的工资为n元,之后每天他的工资都比前一天多d元。
已知煤气灶需要m元,求小j最少工作几天才能买到煤气灶。
第一天,小j的工资为n元,之后每天他的工资都比前一天多d元。
已知煤气灶需要m元,求小j最少工作几天才能买到煤气灶。
输入描述:
四个整数 n,m,d,x
分别表示小j第一天的工资,煤气灶的价格,工资每天的增长量,答案不超过x
输出描述:
一个数表示答案
代码:
等差数列求和
二分直接找就行了
#include <bits/stdc++.h> using namespace std; long long n,m,d; int check(int x){ long long ans=(long long)x*n+(long long)x*(x-1)/2*d; if(ans>=m) return 1; else return 0; } int main() { int x; cin>>n>>m>>d>>x; int l=1,r=x; while(l<r){ int mid=(l+r)/2; if(check(mid)) r=mid; else l=mid+1; } cout<<l<<endl; return 0; }
C 项链
链接:https://ac.nowcoder.com/acm/contest/332/C
来源:牛客网
题目描述
小B想给她的新项链染色。
现在有m种颜色,对于第i种颜色,小B有a_i单位的颜料,每单位颜料可以染项链的一个珠子;
同时,小B对于第i种颜色的喜爱度为b_i。
已知项链有n个珠子,求染色后每个珠子的颜色的喜爱度之和的最大值。
(每个珠子只能至多被染一次,不被染色则喜爱度为0)
现在有m种颜色,对于第i种颜色,小B有a_i单位的颜料,每单位颜料可以染项链的一个珠子;
同时,小B对于第i种颜色的喜爱度为b_i。
已知项链有n个珠子,求染色后每个珠子的颜色的喜爱度之和的最大值。
(每个珠子只能至多被染一次,不被染色则喜爱度为0)
输入描述:
第一行两个数n,m
第二行m个数a_i
第三行m个数b_i
输出描述:
一个数表示答案
代码:
结构体排序,cmp,sort
#include <bits/stdc++.h> using namespace std; struct node{ int sum; int like; }num[100005]; int cmp(node x,node y){ return x.like>y.like; } int main() { int n,m; cin>>n>>m; for(int i=0;i<m;i++) cin>>num[i].sum; for(int i=0;i<m;i++) cin>>num[i].like; sort(num,num+m,cmp); int ans=0; int t=0; for(int i=0;i<n;i++){ while(num[t].sum==0&&t!=m-1){ t++; } if(num[t].sum==0) break; else num[t].sum--; ans+=num[t].like; } cout<<ans<<endl; return 0; }
D 美食:
链接:https://ac.nowcoder.com/acm/contest/332/D
来源:牛客网
题目描述
小B喜欢美食。
现在有n个美食排成一排摆在小B的面前,依次编号为1..n,编号为i的食物大小为 a[i] ,即足够小B吃 a[i] 口。
小B每次会吃两口,这两口要么是编号相同的美食,要么是编号之差的绝对值为1的美食。
小B想知道,她最多能吃几次?
现在有n个美食排成一排摆在小B的面前,依次编号为1..n,编号为i的食物大小为 a[i] ,即足够小B吃 a[i] 口。
小B每次会吃两口,这两口要么是编号相同的美食,要么是编号之差的绝对值为1的美食。
小B想知道,她最多能吃几次?
输入描述:
第1行一个正整数n,表示美食个数
接下来n行,第i行一个整数a[i],表示编号为i的美食的大小
输出描述:
一个数表示小b最多吃几次
代码:
从前到后,和从后到前都暴力一遍
先统计前后,然后在考虑奇偶
#include <bits/stdc++.h> using namespace std; int main() { int n,m; long long ans1=0; int num[100005],num1[100005]; memset(num,0,sizeof(num)); memset(num1,0,sizeof(num1)); cin>>n; for(int i=0;i<n;i++) cin>>num[i],num1[i]=num[i]; for(int i=0;i<n-1;i++){ int t=min(num[i],num[i+1]); ans1+=t; num[i]-=t; num[i+1]-=t; if(num[i]>=2) ans1+=(num[i]/2),num[i]=num[i]%2; } int t=min(num[n-1],num[n-2]); ans1+=t; num[n-1]-=t; num[n-2]-=t; if(num[n-1]>=2) ans1+=num[n-1]/2; long long ans2=0; for(int i=n-1;i>0;i--){ int t=min(num1[i],num1[i-1]); ans2+=t; num1[i]-=t; num1[i-1]-=t; if(num1[i]>=2) ans2+=(num1[i]/2),num1[i]=num1[i]%2; } t=min(num1[0],num1[1]); ans2+=t; num1[0]-=t; num1[1]-=t; if(num1[0]>=2) ans2+=num1[0]/2; cout<<max(ans1,ans2)<<endl; return 0; }
E 海啸
链接:https://ac.nowcoder.com/acm/contest/332/E
来源:牛客网
题目描述
有一个沿海地区,可以看作有n行m列的城市,第i行第j列的城市海拔为h[i][j]。
由于沿海,所以这个地区经常会发生海啸。
海啸发生时,部分城市会被淹没,具体来说,海水高度会达到d,因此海拔低于d的城市都会被淹没。
现在有q次询问,每次问你一个矩形区域中,有多少城市不会被淹没。
由于沿海,所以这个地区经常会发生海啸。
海啸发生时,部分城市会被淹没,具体来说,海水高度会达到d,因此海拔低于d的城市都会被淹没。
现在有q次询问,每次问你一个矩形区域中,有多少城市不会被淹没。
输入描述:
第一行三个整数n,m,d,具体含义见题目描述。
接下来n行,每行m个整数,其中第i行第j列的整数为h[i][j],具体含义见题目描述。
第n+2行一个整数q,表示询问数。
接下来q行,每行四个整数a,b,x,y,
表示询问从第a行第b列到第x行第y列的矩形地区中,有多少地区不会被淹没。
即有多少个i,j,满足 a≤i≤x,b≤j≤ya≤i≤x,b≤j≤y ,且 h[i][j]≥dh[i][j]≥d 。
输出描述:
共q行,每行输出查询的答案
代码:
二维前缀和,加动态生成二维数组
#include <bits/stdc++.h> using namespace std; int main() { int n,m,x,d; cin>>n>>m>>d; int **num = new int*[n+1];//开辟一块内存来存放每一行的地址 for (int i = 0; i <=n; i++)//分别为每一行开辟内存 num[i] = new int[m+1]; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>x; if(x>=d) num[i][j]=1; else num[i][j]=0; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ num[i][j]+=num[i-1][j]+num[i][j-1]-num[i-1][j-1]; } } int q; cin>>q; while(q--){ int a,b,c,d; cin>>a>>b>>c>>d; a--; b--; cout<<num[c][d]+num[a][b]-num[a][d]-num[c][b]<<endl; } return 0; }
G 区间或和
题目描述
求a|(a+1)|(a+2)|...|(b-1)|b。
其中|表示[按位或](https://baike.baidu.com/item/%E6%8C%89%E4%BD%8D%E6%88%96)。
输入描述:
多组输入,每行两个数表示a和b
输出描述:
按题意输出或和
代码:
看到按位或,应该就能想到二进制。
画个图应该就能想到规律了,即从高位向低位走,相同为1就保留,直到第一个不同的数,后面全为1
#include <bits/stdc++.h> using namespace std; void jie(long long a,long long b){ int x[64],y[64]; memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); int ans[64]; memset(ans,0,sizeof(ans)); int t=0; while(a){ x[t++]=a%2; a/=2; } int s=0; while(b){ y[s++]=b%2; b/=2; } int flag=0; for(int i=max(s,t);i>=0;i--){ if(flag==1) ans[i]=1; else { if(x[i]!=y[i]) flag=1,ans[i]=1; else if(x[i]==1) ans[i]=1; } } long long sum=0; long long ou=1; for(int i=0;i<max(s,t);i++){ if(ans[i]) sum+=ou; ou*=2; } cout<<sum<<endl; } int main() { long long a,b; while(cin>>a>>b){ jie(a,b); } return 0; }