第二届云哥杯暨 黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)部分题解
A 数组截取
题目描述
有一段数组n 从中截取和为k的一部分 最长可以截取多长?(如果截取不到正好为k的情况下输出-1)
注意:
出题人:出个数组截取吧;验题人:数据太弱了加强一下;出题人:陷入沉思,OK
本题因为验题人吐槽,数据太弱所以加强了一点点,一点点.......
因为数据比较多 请使用你认为最快的读取方式 最省内存的运算方法。反正C++标程 500ms 256mb 内跑过去了。
输入描述:
第一行输入两个整数 n,k
1<n<=2×107
0<=k<=1018
第二行输入n个正整数(包含0)
a1 a2 .....an (0<=ai<=1012) 1<=i<=n
输出描述:
输出运算结果
备注:
注意数据及其多 请使用快速的读取方式
以及内存很小 不要浪费 哦
思路:
前缀和+双指针。本题最大的坑点在于它的数据范围,java的Scanner读入肯定会超时,所以拿出了本人珍藏已久的java输入挂,秒过了。。。
import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; public class Main { static long[] sum = new long[20000010]; public static void main(String[] args) throws IOException { Reader reader = new Reader(); int n = reader.nextInt(); long k = reader.nextLong(); for(int i=1;i<=n;i++){ long u = reader.nextLong(); sum[i] = sum[i-1] + u; } int res = -1; for(int i=1,j=1;i<=n;i++){ while(j<=i&&getsum(i,j)>k) j++; if(getsum(i,j)==k){ res = Math.max(res,i-j+1); } } System.out.println(res); } public static long getsum(int x,int y){ return sum[x] - sum[y-1]; } } class Reader { final private int BUFFER_SIZE = 1 << 16; private DataInputStream din; private byte[] buffer; private int bufferPointer, bytesRead; public Reader() { din = new DataInputStream(System.in); buffer = new byte[BUFFER_SIZE]; bufferPointer = bytesRead = 0; } public Reader(String file_name) throws IOException { din = new DataInputStream(new FileInputStream(file_name)); buffer = new byte[BUFFER_SIZE]; bufferPointer = bytesRead = 0; } public String readLine() throws IOException { byte[] buf = new byte[64]; // line length int cnt = 0, c; while ((c = read()) != -1) { if (c == '\n') break; buf[cnt++] = (byte) c; } return new String(buf, 0, cnt); } public int nextInt() throws IOException { int ret = 0; byte c = read(); while (c <= ' ') c = read(); boolean neg = (c == '-'); if (neg) c = read(); do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9'); if (neg) return -ret; return ret; } public long nextLong() throws IOException { long ret = 0; byte c = read(); while (c <= ' ') c = read(); boolean neg = (c == '-'); if (neg) c = read(); do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9'); if (neg) return -ret; return ret; } public double nextDouble() throws IOException { double ret = 0, div = 1; byte c = read(); while (c <= ' ') c = read(); boolean neg = (c == '-'); if (neg) c = read(); do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9'); if (c == '.') { while ((c = read()) >= '0' && c <= '9') { ret += (c - '0') / (div *= 10); } } if (neg) return -ret; return ret; } private void fillBuffer() throws IOException { bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE); if (bytesRead == -1) buffer[0] = -1; } private byte read() throws IOException { if (bufferPointer == bytesRead) fillBuffer(); return buffer[bufferPointer++]; } public void close() throws IOException { if (din == null) return; din.close(); } }
B 群友们在排列数字
题目描述
群友们在玩一个游戏,共n个人在玩 每个人要在0-(n-1)中选一个数,注意每个数只能选择一次,
然后按照先后选择顺序拼成一个数,计算组成的数字是否可以整除k,
群友们想知道,如果选择方案不重复,最多有多少种情况可以整除k?
如果不可能整除k请输出-1;
输入描述:
第一行输入两个正整数 n,k
1<=n<=10,1<=k<=107
输出描述:
输出结果
示例1
输入
2 1
输出
2
说明
01 10 两种组合除以1都可以除开
import java.util.Scanner; public class Main{ static long res; static int n,k; static int[] arr = new int[100]; static boolean[] flag = new boolean[100]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); dfs(0); if(res!=0) System.out.println(res); else System.out.println(-1); } public static void dfs(int x){ if(x==n){ long t = 0; for(int i=0;i<n;i++){ t = t*10+arr[i]; } if(t%k==0) res++; return; } for(int i=0;i<n;i++){ if(!flag[i]){ arr[x] = i; flag[i] = true; dfs(x+1); flag[i] = false; } } } }
c gg查成绩
题目描述
这一天gg拿到了一份,超多的考试数据a 。
老师要求他按照询问数据告诉老师,第几个到第几个同学的分数和是多少 ?
gg最近入职字节跳动了,没有时间处理这种极其简单的问题,所以请你顺手秒一下。
输入描述:
第一行n m ( n个同学 m次询问)
1<=n<=106
1<=m<=104
第二行输入n个整数表示成绩
a1 a2 .....an (0<=ai<=100) 1<=i<=n
以下m行为两个整数bi bj 表示第几个到第几个同学(从1开始)
1<=bi<=bj<=n
输出描述:
m行查询结果
示例1
输出
复制110 494 198
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); long n = sc.nextLong(); long m = sc.nextLong(); long[] sum = new long[(int)n+5]; for(int i=1;i<=n;i++){ long t = sc.nextLong(); sum[i] = sum[i-1]+t; } while((m--)>0){ int a = sc.nextInt(); int b = sc.nextInt(); System.out.println(sum[b]-sum[a-1]); } } }
D issue与lifehappy给学生分组
题目描述
issue与lifehappy在给学生分组 现在他们手里有一组n分学生量化好的数据a 这份数据是一个数字,代表学生的大致实力
他们要给学生分成m组并且要求总实力和的最大值最小(ccpc抢名额战略,分散一点)
不过学生们已经拉帮结派的排好队了 所以 issue与lifehappy只能选取这组数据中的连续队列。输入描述:
第一行 n m n个学生 分成m组
1<=m<=n<=106
第二行为n正整数an
a1 a2 .....an (0<=ai<=1011) 1<=i<=n(保证最终结果在ull内)输出描述:
输出分组后总实力最大值的最小
示例1
输入
5 3 1 8 9 4 2
输出
9
思路:
二分枚举答案。
import java.io.*; public class Main{ static int n,m; static long[] arr = new long[1000100]; public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); String[] str = bufferedReader.readLine().split(" "); n = Integer.valueOf(str[0]); m = Integer.valueOf(str[1]); long s = 0; long l = -1; String[] sss = bufferedReader.readLine().split(" "); for(int i=0;i<n;i++){ arr[i] = Long.valueOf(sss[i]); s += arr[i]; l = Math.max(arr[i],l); } long r = s+1; while(l<r){ long mid = l+r>>1; if(check(mid)) r = mid; else l = mid+1; } System.out.println(r); } public static boolean check(long x){ int cnt = 1; long sum = 0; for(int i=0;i<n;i++){ if(sum+arr[i]<=x) sum += arr[i]; else{ cnt++; sum = arr[i]; } } return cnt<=m; } }
E 删删删越小越好
题目描述
这一天Kadia与Majiagou在教学弟,
突然提出了一个问题 给你一个超大的数字 让你从中删掉几位 怎么让他最小?
这种签到题不会还有人写不出来吧 不会吧不会吧
输入描述:
第一行输入一个整数N
1<=len(N)<=2×107
第二行输入一个整数k代表删除几个数字
0<=k<=len(N)
输出描述:
输出结果
示例1
输入
10000 1
输出
0
说明
删掉1结果为0
示例2
输入
12347897187194164979 10
输出
1114164979
思路:
两个char数组,a数组储存答案。当a数组最后一个数大于当前数时删除a数组最后一个数。注意数据升序的情况。
import java.io.*; public class Main{ public static void main(String[] args) throws IOException { BufferedReader sc = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter out= new BufferedWriter(new OutputStreamWriter(System.out)); char[] ch = sc.readLine().toCharArray(); int k = Integer.valueOf(sc.readLine()); char[] a = new char[20000010]; int top = 0; int cnt = 0; for(int i=0;i<ch.length;i++){ while(cnt!=k&&a[top]>ch[i]&&top!=0){ top--; cnt++; } a[++top] = ch[i]; } boolean flag = false; for(int i=1;i<=top-(k-cnt);i++){ if(a[i]!='0'){ flag = true; } if(flag) out.write(a[i]+""); } if(!flag) System.out.print(0); out.flush(); } }
F happy的异或运算
题目描述
我们都知道有一种位运算叫做异或,那么这道题是一道思维题。
给出一个整数n,请求出1-n之间选取两个数进行异或最大能得出多大?(两个数可以相同)
输入描述:
1 ≤ N ≤1018
输出描述:
无
示例3
输出
复制511
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); long n = sc.nextLong(); String str = Long.toBinaryString(n); if(str.equals("1")){ System.out.print(0); return; } String res = ""; for(int i=0;i<str.length();i++) res += 1; System.out.print(Long.parseLong(res,2)); } }
G Alan%%%
题目描述
又是欢快的一天,牛客多校算法训练营4又在日常%Alan。qcjj想知道到底Alan被%了多少次,所以整理了一下聊天记录。
如果一句话中存在Alan,那么那句话中的%都算%了Alan。由于可能话中有空格,所以去掉空格后形成的Alan也算Alan。
输入描述:
第一行输入整数n表示聊天记录行数
1<=n<=1000
以下n行每行一个字符串s代表聊天记录
1<=s.length<=1000
输出描述:
输出%Alan次数
示例1
输入
5 %alan%% %Alan%%% cdqwsq%% A l a n%% %AC lan%% %Alan%%%
输出
12
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int res = 0; sc.nextLine(); for(int i=0;i<n;i++){ String[] arr = sc.nextLine().split(" "); String str = ""; for(int j=0;j<arr.length;j++) str+=arr[j]; if(str.contains("Alan")){ char[] ch = str.toCharArray(); for(int j=0;j<str.length();j++) if(ch[j]=='%') res++; } } System.out.print(res); } }