牛客寒假算法基础集训营6 题解
A出题
链接:https://ac.nowcoder.com/acm/contest/332/A 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
小B准备出模拟赛。
她把题目按难度分为四等,分值分别为6,7,8,9。
已知小B共出了m道题,共n分。
求小B最少出了多少道6分题。
输入描述:
两个正整数n,m
输出描述:
一个数,表示答案。
若无解,输出"jgzjgzjgz"。
示例1
输入
复制
34 5
输出
复制
1
示例2
输入
复制
32 5
输出
复制
3
示例3
输入
复制
5 1
输出
复制
jgzjgzjgz
备注:
n,m≤1012
分析:
无解:6m>n或n>9m 。
有解:
设6,7,8,9分的题数为a,b,c,d,
则:
n=6a+7b+8c+9d
m=a+b+c+d
得出,
a=7*m-n+c+2*d
7*m-n是固定的,c+2*d是随便的数,因为我们知道我们这种情况肯定有解。
所以a的最小值为7*m-n
官方题解:
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
Long n=in.nextLong();
Long m=in.nextLong();
if(n<6*m||n>9*m)
{System.out.println("jgzjgzjgz");return ;}
Long ans=(long) (1<<30);
if(7*m-n>=0)
System.out.println(7*m-n);
else
System.out.println(0);
}
}
B 煤气灶
链接:https://ac.nowcoder.com/acm/contest/332/B 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
小j开始打工,准备赚钱买煤气灶。
第一天,小j的工资为n元,之后每天他的工资都比前一天多d元。
已知煤气灶需要m元,求小j最少工作几天才能买到煤气灶。
输入描述:
四个整数 n,m,d,x
分别表示小j第一天的工资,煤气灶的价格,工资每天的增长量,答案不超过x
输出描述:
一个数表示答案
示例1
输入
复制
10 100 20 100
输出
复制
4
说明
10+30+50+70>=100
备注:
0≤n,d≤109,n+d>00≤n,d≤109,n+d>0
1≤m≤10181≤m≤1018
1≤x≤109
我的解直接二分的答案
官方题解:
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
Long n=in.nextLong();
Long m=in.nextLong();
Long d=in.nextLong();
Long x=in.nextLong();
Long l=(long) 1;
Long r=x;
while(l<r)
{
Long mid=(l+r)>>1;
Long f=mid*n+mid*(mid-1)/2*d;
if(f>=m)
{
r=mid;
}
else
l=mid+1;
}
System.out.println(l);
}
}
C项链
很裸的贪心
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 20007
using namespace std;
struct node
{
int x,y;
}a[100005];
bool cmp(node q,node w)
{
return q.y>w.y;
}
int main ( )
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
scanf("%d",&a[i].x);
for(int i=1;i<=m;i++)
scanf("%d",&a[i].y);
sort(a+1,a+m+1,cmp);
long long ans=0;
for(int i=1;i<=m&&n>0;i++)
{
//cout<<a[i].x<<" "<<a[i].y<<" "<<n<<endl;
if(n>=a[i].x)
{
ans=ans+(long long)(a[i].x*a[i].y);
n-=a[i].x;
}
else
{
ans=ans+(long long)((n)*a[i].y);
break;
}
}
cout<<ans<<endl;
return 0;
}
D美食
贪心
i从1到n枚举,依次贪心。
对于a[i],
首先把答案加上a[i]/2,
如果a[i]是奇数且a[i+1]>0,则把a[i+1]减去1,答案加上1。
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
Long []a=new Long[100005];
Long n=in.nextLong();
for(int i=1;i<=n;i++)
{
a[i]=in.nextLong();
}
Long ans=(long) 0;
a[(int) (n+1)]=(long) 0;
for(int i=1;i<=n;i++)
{
ans+=a[i]/2;
if(a[i]%2==1&&a[i+1]!=0)
{a[i+1]--;ans++;}
}
System.out.println(ans);
}
}
海啸
链接:https://ac.nowcoder.com/acm/contest/332/E
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有一个沿海地区,可以看作有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,满足 a≤i≤x,b≤j≤ya≤i≤x,b≤j≤y ,且 h[i][j]≥dh[i][j]≥d 。
输出描述:
共q行,第i行一个整数,表示第i个询问的答案。
示例1
输入
复制
3 3 3
1 2 3
2 1 5
4 3 2
2
1 2 2 3
2 1 3 3
输出
复制
2
3
备注:
1≤n×m≤1061≤n×m≤106
1≤q≤1051≤q≤105
0≤d,h[i][j]≤1090≤d,h[i][j]≤109
1≤a≤x≤n,1≤b≤y≤m
运用一个二维前缀和即可
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
Reader.init(System.in);
int n=Reader.nextInt();
int m=Reader.nextInt();
int d=Reader.nextInt();
int [][]sum=new int[n+1][m+1];
for(int i=1;i<=n;i++)
{
sum[i]=new int[m+1];
for(int j=1;j<=m;j++)
{
int x=Reader.nextInt();
if(x>=d)
sum[i][j]=1;
else
sum[i][j]=0;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
int q=Reader.nextInt();
while(q-->0)
{
int l1=Reader.nextInt(),r1=Reader.nextInt(),l2=Reader.nextInt(),r2=.nextInt();
int ans=sum[l2][r2] + sum[l1 - 1][r1 - 1] - sum[l1 - 1][r2] - sum[l2][r1 - 1];
System.out.println(ans);
}
// System.out.println(ans);
}
}
class Reader
{
static BufferedReader reader;
static StringTokenizer tokenizer;
static void init(InputStream input)
{
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens())
{
String str=reader.readLine();
//System.out.println(str);
tokenizer = new StringTokenizer(str);
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException
{
return Integer.parseInt(next());
}
static double nextDouble() throws IOException
{
return Double.parseDouble(next());
}
}
石头剪刀布
待补
根据获胜者的偏爱决策可以推出对战的两人的偏爱决策,所以枚举最终获胜者的偏爱决策判断一下就好了。字典序问题只需递归处理+暴力 cmp 。
时间 O(2n×n)O(2n×n)
G 区间或和
链接:https://ac.nowcoder.com/acm/contest/332/G 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
求a|(a+1)|(a+2)|...|(b-1)|b。
其中|表示[按位或](https://baike.baidu.com/item/%E6%8C%89%E4%BD%8D%E6%88%96)。
输入描述:
多组输入,每行两个数表示a和b
输出描述:
对于每组输入,输出一个数a|(a+1)|(a+2)|...|(b-1)|b。
示例1
输入
复制
99 109
68 77
55 66
34 43
1111234 1114321
输出
复制
111
79
127
47
1179647
备注:
输入不超过10000行,0≤a,b≤10180≤a,b≤1018,a≤b
规律题:
发现当一个数按位或一个比它大的数的时候它才会变,那么我们对于a和b,依次枚举ans按位或ans+1,直到大于等于b就好了。
官方题解:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ll a,b;
while(scanf("%lld%lld",&a,&b) != EOF){
while(a < b){
a|= (a + 1);
}
printf("%lld\n", a);
}
return 0;
}
肥猪
待补
从0到n-1枚举第二种操作的使用次数step,
那么对于最终得到的编号为i的肥猪,
假如它是召唤编号为j的肥猪然后进化多次得到的,
则一定有 i−step≤j≤ii−step≤j≤i ,
并且这是充要的,即它可以由这个区间的任何一个j召唤后进化多次得到。
因此只用这个区间的a[j]的最小值就是得到i的代价。
把所有i的代价相加再加上step*x就是step对应的最小代价。
注意,这个题目是一个环而不是链,这只需要将a复制一份即可。
求区间最小值有很多方法,比如单调队列。
时间复杂度 O(n2)O(n2) 。
I wzoi
链接:https://ac.nowcoder.com/acm/contest/332/I 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
bleaves 最近在 wzoi 上面做题。
wzoi 的题目有两种,一种是 noip 题,一种是省选题。
bleaves 的做题方式很特别。每一天,她可能会看一道题目,这时她会选择题目种类,然后 wzoi 会在选定种类中随机扔给她一道她还没看过的题,她会把这道题看一遍,然后存在脑子里慢慢思考;她也有可能写题,这时她一定会写没写过的题中看的时间最迟的一题(如果不存在没写过的且没看过的题,她就不能写题)。
wzoi 每天会有一个推荐的题目种类,
如果 bleaves 看一道题目:如果种类和推荐的相同,那么这道题目最大得分为10,否则为5
如果 bleaves 写一道题目:如果种类和推荐的相同,那么这道题目得分为最大得分,否则为最大得分-5
假如 bleaves 现在还没看过任何一题,并且她知道了 wzoi 接下来一些天每天推荐的种类,问她在这些天的最大得分。
输入描述:
一行一个01串 s ,|s| 表示天数,si=0si=0 表示 wzoi 第 i 天推荐 noip 题, si=1si=1 表示 wzoi 第 i 天推荐省选题。
输出描述:
一行一个整数最大得分。
示例1
输入
复制
0011
输出
复制
20
说明
4天行动依次为:看一道 noip 题,写第1天看的题,看一道省选题,写第3天看的题。
示例2
输入
复制
0101
输出
复制
10
说明
4天行动依次为:看一道 noip 题,写第1天看的题,看一道noip题,写第3天看的题。
示例3
输入
复制
0110
输出
复制
20
说明
4天行动依次为:看一道 noip 题,看一道省选题,写第2天看的题,写第1天看的题。
备注:
全部的输入数据满足:1≤n≤1061≤n≤106 , n 为偶数。
分析:
其实这题算一个贪心,因为它要做最后看到的题,最优的策略00 11就能得到10分,删除他们,剩下的能得到5分,用栈模拟一个删除过程即可
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
Reader.init(System.in);
char[] s=in.next().toCharArray();
int ans=0;
int cnt=0;
Stack<Character> s1=new Stack<Character>();
for(int i=0;i<s.length;i++)
{
if(s1.size()==0)
{
s1.push(s[i]);
continue;
}
if(s[i]==s1.peek())
{
s1.pop();
ans+=10;
}
else
{
s1.push(s[i]);
}
}
ans=ans+s1.size()/2*5;
System.out.println(ans);
}
}
class Reader
{
static BufferedReader reader;
static StringTokenizer tokenizer;
static void init(InputStream input)
{
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens())
{
String str=reader.readLine();
//System.out.println(str);
tokenizer = new StringTokenizer(str);
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException
{
return Integer.parseInt(next());
}
static double nextDouble() throws IOException
{
return Double.parseDouble(next());
}
}
J迷宫
链接:https://ac.nowcoder.com/acm/contest/332/J 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
你在一个 n 行 m 列的网格迷宫中,迷宫的每一格要么为空,要么有一个障碍。
你当前在第 r 行第 c 列(保证该格子为空)。每次移动你可以向上下左右任意一个方向移动一格,前提是不能走到障碍上,也不能超出迷宫的边界。
你向左移动的次数不能超过 x 次,向右不能超过 y 次。
问在这种情况下,对于每个格子,是否存在一种移动方案让你走到它。
输出有多少个格子存在移动方案让你走到它。
输入描述:
第一行两个正整数 n,m 。
第二行两个正整数 r,c ,保证 1≤r≤n1≤r≤n ,1≤c≤m1≤c≤m 。
第三行两个整数 x,y ,保证 0≤x,y≤1090≤x,y≤109 。
接下来 n 行,每行一个长度为 m 的字符串,
第 i 行第 j 个字符表示迷宫第 i 行第 j 列的格子,
字符为`.` 表示格子为空,字符为`*` 表示格子上有一个障碍。
输出描述:
输出一个数,表示有多少个格子存在移动方案让你走到它。
示例1
输入
复制
4 5
3 2
1 2
.....
.***.
...**
*....
输出
复制
10
说明
将能走到的格子用+标记:
+++..
+***.
+++**
*+++.
示例2
输入
复制
4 4
2 2
0 1
....
..*.
....
....
输出
复制
7
说明
.++.
.+*.
.++.
.++.
备注:
对于全部数据, 1≤n,m≤10001≤n,m≤1000 。
这题简单的bfs就能过
不过题解给了啥:
这题数据
import java.io.BufferedInputStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class node
{
int x,y,ls,rs;
public node(int x, int y, int ls, int rs) {
super();
this.x = x;
this.y = y;
this.ls = ls;
this.rs = rs;
}
@Override
public String toString() {
return "node [x=" + x + ", y=" + y + ", ls=" + ls + ", rs=" + rs + "]";
}
}
public class Main {
static int [] dx={1,0,-1,0};
static int [] dy={0,1,0,-1};
static int n,m,x,y;
static String[] map =new String[1005];
static int[][] vis =new int[1005][1005];
public static int bfs(int x1,int y1)
{
Queue<node> q=new LinkedList<node>();
node a = new node(x1,y1,0,0);
q.offer(a);
int ans=1;
vis[x1][y1]=1;
while(q.size()!=0)
{
a=q.poll();
//System.out.println(a);
for(int i=0;i<4;i++)
{
node b=null;
if(i==1)
{
b=new node(a.x+dx[i],a.y+dy[i],a.ls,a.rs+1);
}
else if(i==3)
b=new node(a.x+dx[i],a.y+dy[i],a.ls+1,a.rs);
else
b=new node(a.x+dx[i],a.y+dy[i],a.ls,a.rs);
if(b.x>=0&&b.x<n&&b.y>=0&&b.y<m&&map[b.x].charAt(b.y)!='*'&&b.ls-b.rs<=x&&b.rs-b.ls<=y&&vis[b.x][b.y]==0)
{
ans++;
q.offer(b);
vis[b.x][b.y]=1;
}
}
}
return ans;
}
public static void main(String[] args) {
//Scanner in = new Scanner (new BufferedInputStream(System.in));
Scanner in = new Scanner(new BufferedInputStream(System.in));
n=in.nextInt();
m=in.nextInt();
int r=in.nextInt();
int c=in.nextInt();
r--;
c--;
x=in.nextInt();
y=in.nextInt();
in.nextLine();
for(int i=0;i<n;i++)
{
map[i]=new String();
map[i]=in.next();
}
System.out.println(bfs(r,c));
}
}
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;++i)
const int N=2000+5,inf=1e9;
char s[N][N];
int g[N][N];
deque<int>q;
int n,m,r,c;
void bfs()
{
rep(i,1,n)
rep(j,1,m)g[i][j]=inf;
g[r][c]=0;
q.push_back(r*N+c);
while(!q.empty())
{
int x=q.front();q.pop_front();
int y=x%N;x/=N;
if(s[x-1][y]=='.'&&g[x-1][y]>g[x][y])
{
g[x-1][y]=g[x][y];
q.push_front((x-1)*N+y);
}
if(s[x+1][y]=='.'&&g[x+1][y]>g[x][y])
{
g[x+1][y]=g[x][y];
q.push_front((x+1)*N+y);
}
if(s[x][y-1]=='.'&&g[x][y-1]>g[x][y]+1)
{
g[x][y-1]=g[x][y]+1;
q.push_back(x*N+y-1);
}
if(s[x][y+1]=='.'&&g[x][y+1]>g[x][y]+1)
{
g[x][y+1]=g[x][y]+1;
q.push_back(x*N+y+1);
}
}
}
int main()
{
//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);
cin>>n>>m>>r>>c;
int x,y;
cin>>x>>y;
rep(i,1,n)scanf("%s",s[i]+1);
bfs();
int ans=0;
rep(i,1,n)
rep(j,1,m)
if(g[i][j]!=inf)
{
int a=j-c;
int b=g[i][j];
ans+=(b-a)/2<=x&&(b+a)/2<=y;
}
cout<<ans;
}
std
https://ac.nowcoder.com/acm/contest/332#submit/{%22searchUserName%22%3A%22kczno1%22}