计蒜客2019 蓝桥杯省赛 B 组模拟赛(一)

A. 结果填空:钟表
直接手算即可 30:24:26 - 22:28:45 = 07:55:41 。
B. 结果填空:青蛙爬井
按题意模拟即可
代码如下:

public class Main {
    public static void main(String[] args) {
        int high = 60405, up = 105, dow = 35;
        int day = 1, ans = 0;
        while (ans <= high) {
            ans += up;
            if (ans >= high) {
                break;
            }
            ans -= dow;
            day++;
        }
        System.out.println(day);
    }
}

C. 结果填空:倍数
最一开始是想用大数直接暴力做,然后就是各种超时,后来有个思路就是就是 1 到 n 有多少个是 m 倍数,个数为 n/m,所以这道题即:r/d - l/d,答案为:52573230519
代码如下:

public class Main {
    public static void main(String[] args) {
        long l = 1032, r = 12302135942453l, d = 234;
        long res = r / d - (l - 1)/ d;
        System.out.println(res);
    }
}

E. 代码填空:LIS
求LIS最长上升子序列可以用dp或者二分来做,去年貌似也有这个题,不过那个题是用dp,这题用的是二分,代码填空题可以直接猜题意,比如上面有一个二分法的函数,但其他都没用过,所以这个函数肯定需要调用,而且二分法有返回值,而且发现没有定义 k ,所以这个调用二分法的返回值就是 k ,其他的三个参数就可以多试试看,比如前两个参数是二分法的范围,有可能是 0 到 n-1,也可能0 到 len,也可能len 到n-1,根据下面代码出现了len,所以有len的可能性更大。最后一个参数是要找的数,结合下面的代码,那就猜测是a[i] .
答案:int k = find(0,len,a[i]);
F. 程序设计:找质数
题目: 一天蒜头君猜想,是不是所有的偶数(除了 2),都可以用两个质数相加得到呢?于是聪明的蒜头君就找你来验证了。
输入格式
第一行输入一个整数 t表示测试组数。
接下来 t 行,每行一个整数 n。
输出格式
输出两个整数,因为答案可能有多个,所有要求输出的这两个整数是所有答案中字典序最小的。

思路:思路:先利用打表把所有素数找出来,然后从2开始判断,当 i 为素数 且 n-i 也为素数,那么这个就是答案,进行输出。而打表素数的方法,数据大,用线性筛,筛选素数表。
AC代码:

import java.util.Scanner;

public class Main {
    static int t;
    static int n;
    static boolean[] prime = new boolean[1000010];

    public static void Prime() {
        for (int i = 2; i <= 1000000; i++) {
            prime[i] = true;
        }
        for (int i = 1; i * i <= 1000000; i++) {
            if (prime[i]) {
                for (int j = i * i; j <= 1000000; j += i) {
                    prime[j] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        t = cin.nextInt();
        Prime();
        while (t-- > 0) {
            n = cin.nextInt();
            for (int i = 2;; i++) {
                if (prime[i] && prime[n - i]) {
                    System.out.println(i + " " + (n - i));
                    break;
                }
            }
        }
    }
}

G. 程序设计:后缀字符串
一天蒜头君得到 n个字符串Si,每个字符串的长度都不超过 10.
蒜头君在想,在这 n个字符串中,以 Si为后缀的字符串有多少个呢?
输入格式
第一行输入一个整数 n。
接下来 n 行,每行输入一个字符串 Si 。
输出格式
输出 n个整数,第 ii 个整数表示以Si为后缀的字符串的个数。

最一开始直接模拟暴力求解,只通过了50%的数据,思路大概就是将当前该字符串和其他字符串进行比较,如果其他字符串的长度比自己小,说明不可能是后缀,如果长的话,就进行比较。
50%数据通过代码——模拟暴力:

import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int n = cin.nextInt();
		String[] s = new String[n + 5];
		for (int i = 0; i < n; ++i) {
			s[i] = cin.next();
		}
		boolean flag;
		int ret = 0;
		int len = 0;
		for (int i = 0; i < n; ++i) {
			ret = 1;
			for (int j = 0; j < n; ++j) {
				if (i == j) {
					continue;
				}
				len = s[j].length() - s[i].length();
				if (len < 0) {
					continue;
				}
				flag = true;
				for (int k = 0; k < s[i].length(); k++) {
					if (s[i].charAt(k) != s[j].charAt(k + len)) {
						flag = false;
						break;
					}
				}
				if (flag)
					ret++;
			}
			System.out.println(ret);
		}
	}
}

看了题解之后是可以用map做,可以通过100%的数据。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
const int N = 100005;
string a[N];
int main() {
    map<string, int> mp;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        for (int j = 0; j < a[i].size(); j++) {
            mp[a[i].substr(j)]++;
        }
    }
    for (int i = 0; i < n; i++) {
        cout << mp[a[i]] << endl;
    }
    return 0;
}

H. 程序设计:轻重搭配
n 个同学去动物园参观,原本每人都需要买一张门票,但售票处推出了一个优惠活动,一个体重为 x 的人可以和体重至少为 2x 配对,这样两人只需买一张票。现在给出了 n个人的体重,请你计算他们最少需要买几张门票?
输入格式
第一行一个整数 n,表示人数。
第二行 n 个整数,每个整数 ai表示每个人的体重。
输出格式
一个整数,表示最少需要购买的门票数目。
很明显,采用贪心,并且需要用双指针,类似二分
思路:贪心,选错贪心思路,只能过一小部分数据,正确贪心思路:从前一半遍历,在后一半中找到比当前元素的两倍大的数,并不是最小的与最大的搭配。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] a = new int[n + 5];
        for (int i = 0; i < n; ++i) {
            a[i] = cin.nextInt();
        }
        Arrays.sort(a, 0, n);
        int ans = n, ret = n / 2;
        for (int i = 0; i < n / 2; ++i) {
            while (ret < n && a[ret] < a[i] * 2)
                ret++;
            if (ret == n)
                break;
            ans--;
            ret++;
        }
        System.out.println(ans);
    }
}

J. 程序设计:蒜厂年会
在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 n 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币。但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币。因为这些数字都是可见的,所以大家都是不会出现的赔的情况。
游戏规则:每人只能抓一次,只能抓取一段连续的纸团,所有纸团上的数字和就是你可以获得的蒜币。
蒜头君作为蒜厂的一员在想,我怎么可以获得最多的蒜币呢?最多能获取多少蒜币呢?
因为年会是发奖,那么一定有大于 0 的纸团。
输入格式
第一行输入一个整数 n,表示有 n 个纸团。
第二行输入输入 n 个整数 ai,表示每个纸团上面写的数字(这些纸团的输入顺序就是环形桌上纸团的摆放顺序)。
输出格式
输出一个整数,表示蒜头君最多能获取多少蒜币。

做法:暴力,只过了60%的数据,枚举数组的起点,环形数组通过把0~起点这段数据搬运到尾部,形成新的数组。再对新数组求前缀和,找出最大的前缀和

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        long[] a = new long[200100];
        long[] ans = new long[200100];
        for (int i = 1; i <= n; ++i) {
            a[i] = cin.nextInt();
        }
        long max = -1;
        // 把环形数组拆分成普通数组
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j < i; ++j) {
                a[n + j] = a[j];
            }
            int len = n + i;
            ans[i - 1] = 0;
            for (int k = i; k <= len; ++k) {
                ans[k] = ans[k - 1] + a[k];
                if (ans[k] > max)
                    max =ans[k];
            }
        }
        System.out.println(max);
    }
}

dp做法后面再补…

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值