牛客寒假算法基础集训营6

A 出题

链接:https://ac.nowcoder.com/acm/contest/332/A
来源:牛客网

题目描述

小B准备出模拟赛。
她把题目按难度分为四等,分值分别为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最少工作几天才能买到煤气灶。

输入描述:

四个整数 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)    

输入描述:

第一行两个数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想知道,她最多能吃几次?

输入描述:

第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次询问,每次问你一个矩形区域中,有多少城市不会被淹没。

输入描述:

第一行三个整数n,m,d,具体含义见题目描述。
接下来n行,每行m个整数,其中第i行第j列的整数为h[i][j],具体含义见题目描述。
第n+2行一个整数q,表示询问数。
接下来q行,每行四个整数a,b,x,y,
表示询问从第a行第b列到第x行第y列的矩形地区中,有多少地区不会被淹没。
即有多少个i,j,满足 aix,bjya≤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;
}

 



posted @ 2019-03-02 19:54  maybe96  阅读(130)  评论(0编辑  收藏  举报