首页 > 技术文章 > 第二届云哥杯暨 黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)部分题解

fxzemmm 2021-01-23 22:51 原文

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

输出描述:

输出运算结果
示例1

输入

复制 
10 3
3 3 1 1 1 0 0 0 3 3

输出

复制 
6
示例2

输入

复制 
10 3
6 6 6 6 6 6 6 6 6 3

输出

复制 
1

备注:

注意数据及其多 请使用快速的读取方式
以及内存很小 不要浪费 哦
 

思路:

前缀和+双指针。本题最大的坑点在于它的数据范围,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

输入

复制 
10 3
11 22 33 44 55 66 77 88 99 10
1 4
2 10
5 7

输出

复制 
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 ≤10
18

输出描述:

示例1

输入

复制 
10000

输出

复制 
16383
示例2

输入

复制 
648

输出

复制 
1023
示例3

输入

复制 
324

输出

复制 
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);
    }
}

 

推荐阅读