A~F 小白月赛94> 我的自动WA机又出手了, 狠狠掉分
A 九宫格
读入,按位置输出即可
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
int[] a = new int[10];
for (int i = 1; i < 10; i++) a[i] = I();
String s = S();
for (char ch : s.toCharArray()) pw.print(a[ch - '0']);
pw.flush();
}
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in), 65535);
static StreamTokenizer st = new StreamTokenizer(bf);
static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
static int I() throws IOException {
st.nextToken();
return (int) st.nval;
}
static String S() throws IOException {
String res = bf.readLine();
while (res.isEmpty()) res = bf.readLine();
return res;
}
}
B 好数组
(1) 数组已经是有序的, 不管怎么选都是有序的, 选不了, 输出0
(2) 数组不是有序的, 全部选上就行了, 输出n
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
int n = I();
int[] a = new int[n];
for (int i = 1; i < n; i++) a[i] = I();
System.out.println(check(a, n) ? 0 : n);
}
static boolean check(int[] a, int n) {//a是否有序
for (int i = 0; i < n - 1; i++) {
if (a[i] > a[i + 1]) return false;
}
return true;
}
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in), 65535);
static StreamTokenizer st = new StreamTokenizer(bf);
static int I() throws IOException {
st.nextToken();
return (int) st.nval;
}
}
C 数字合并最大化极差
最终情况是:
左边一坨合一起, 中间是最小值, 右边一坨合一起
左右取最大值
所以处理出前后缀和, 然后枚举a[i]作为最小值
服了, 索引从1开始还是从0开始啥的一直搞不清, WA了14发, 给我打红温了
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
int n = I();
long[] a = new long[n + 1];
long[] preSum = new long[n + 1];//前缀和,[1,i]
for (int i = 1; i <= n; i++) {
a[i] = I();
preSum[i] = preSum[i - 1] + a[i];
}
long suffSum = preSum[n];//后缀和,a[i+1,n]
long ans = 0;
for (int i = 1; i <= n; i++) {//枚举min
suffSum -= a[i];
ans = Math.max(ans, preSum[i - 1] - a[i]);// 左边合并
ans = Math.max(ans, suffSum - a[i]); // 右边合并
}
System.out.println(ans);
}
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in), 65535);
static StreamTokenizer st = new StreamTokenizer(bf);
static int I() throws IOException {
st.nextToken();
return (int) st.nval;
}
}
D gcd排列构造
a[i] = gcd(ans[1],...ans[i])
a[i-1] = gcd(ans[1],...ans[i-1]
∴ a[i] = gcd(a[i-1],ans[i])
∴ a[i-1]%a[i]=0, ans[i]%a[i]=0
由 a[i-1] % a[i] = 0可知,a是一个非增序列, a[i-1]与a[i]只有两种情况, a[i-1]==a[i], a[i-1]>a[i]
现在从前往后依次确定ans:
(1) 如果a[i - 1] > a[i]:
意味着a[i]是第一次出现, 那么数a[i]一定是没使用过的, 该位需要填a[i]
证明:
a[i-1] = gcd(ans[1],...ans[i-1]) > a[i] = gcd(ans[1],...ans[i])
min(ans[1],...ans[i-1]) > min(ans[1],...ans[i])
min(ans[1],...ans[i-1]) > ans[i]
∴ ans[1]~ans[i-1] 与 ans[i] 不相等, a[i]一定未使用
填a[i]是否会导致无解:
例如: a[i-1] = 4, a[i] = 2, n≥6
显然6也可以填, 那么2可以填在哪
如果 a[i+1] = 2, 则2可以填在i+1位, 这样的话,2与6可以互换, 不影响正确性
如果 a[i+1] = 1, 则后面都是1, 可填数字是任意的, 2和6依旧可以互换
所以填a[i] 不会导致无解
(2) 如果a[i-1] = a[i]:
那么需要找一个a[i]的未使用倍数
填多少倍:
与1的互换同理, 找一个最小的满足条件的倍数即可
从哪开始找:
不能直接从a[i]开始查找, 数组a末尾有很长串的1, 会超时
∵ a[i] = gcd(ans[1],...ans[i])
∴ ans[i]是a[i]的倍数, ans[i-1]也是a[i]的倍数, 且 ans[i] > ans[i-1]
所以可以从ans[i-1]+a[i]开始查找
import java.io.*;
public class Main {
static int N = (int) 2e5 + 1;
static int[] a = new int[N];//a[i] = gcd(ans[1],...asn[i])
static int[] ans = new int[N];
static int n;
static boolean[] used = new boolean[N];//used[i]:数字i是否被使用了
public static void main(String[] args) throws Exception {
n = I();
if (!solve()) {
System.out.println(-1);
} else {
for (int i = 1; i <= n; i++) System.out.print(ans[i] + " ");
}
}
private static boolean solve() throws IOException {
for (int i = 1; i <= n; i++) {
a[i] = I();
/*
a[i] = gcd(ans[1],...ans[i]) = gcd(a[i-1],ans[i])
⇒ a[i-1] % a[i] == 0
*/
if (a[i - 1] % a[i] != 0) return false;
}
for (int i = 1; i <= n; i++) {
if (a[i - 1] != a[i]) {// eg: i=2, a[1]=4, a[2]=2 -> 填2
ans[i] = a[i];
} else {// eg: i=2, a[1]=4, a[2]=4 -> 可填 8 12 16...
ans[i] = find(i);
if (ans[i] == 0) return false;// 找最小的未填的a[i]倍数,找不到
}
used[ans[i]] = true;
}
return true;
}
/**
查找a[i]的未使用的倍数, 且满足:
gcd(ans[1],...ans[i-1],ans[i]) == a[i]
⇔ gcd(a[i-1], ans[i]) == a[i]
*/
static int find(int i) {
// ans[i] > ans[i-1], ans[i-1]也是a[i]的倍数
for (int f = ans[i - 1] + a[i]; f <= n; f += a[i]) {
if (!used[f] && gcd(a[i - 1], f) == a[i]) {
return f;
}
}
return 0;
}
static int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in), 65535);
static StreamTokenizer st = new StreamTokenizer(bf);
static int I() throws IOException {
st.nextToken();
return (int) st.nval;
}
}
E F "与"背包
与运算, 选的越多, 价值越低, 但总体积也越小越可行
现在需要找到最大价值, 设其为ans
∴ value[1] & value[2] & ... = ans
∴ ans & value[i] = ans (ans在任意一位的1, 每个value在对应位上都有)
假设ans = 10110
那么只要第1位、第3位、第4位都为1, 那么这个物品对于这个答案来说就是可选的
而体积是选的越多越可行, 所以可以枚举答案
然后按"ans & value[i] = ans"这个条件,选出所有物品
计算出这些物品的总体积, 如果满足容量k限制, 则找到一个可行解
对于E, 数据范围2e3, 可以直接从2000开始枚举答案
对于F, 数据范围1e9, 可以从高位开始, 用试填法, 逐位确定
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
int n = I(), k = I();
int[] v = new int[n], w = new int[n];//v价值,w重量
for (int i = 0; i < n; i++) {
w[i] = I();
v[i] = I();
}
System.out.println(solve2(n, v, w, k));
}
/**
n,k,w,v ∈ [0,2e3]
枚举答案, 将可选的价值都选上, 计算出重量, 如果满足容量条件, 则找到一个可行解
@param v 价值
@param w 重量|体积
*/
private static int solve1(int n, int[] v, int[] w, int k) {
for (int guess = 2000; guess > 0; guess--) {//枚举答案,总价值
//计算重量是否超标
int weight = (1 << 20) - 1;
for (int i = 0; i < n; i++) {
if ((v[i] & guess) == guess) {// &{v[i]} = guess => (guess & v[i]) = guess
weight &= w[i];
}
}
if (weight <= k) return guess;
}
return 0; //啥也选不了, 空包
}
/**
n,k,w,v ∈ [0,1e9]
从高到低, 试填法确定每一位
*/
private static int solve2(int n, int[] v, int[] w, int k) {
int ans = 0;
for (int bit = 30; bit >= 0; bit--) {//从高位枚举
int guess = ans | (1 << bit);//尝试在该位填1
int weight = (1 << 30) - 1;// 1e9 < 2^30
for (int i = 0; i < n; i++) {
if ((guess & v[i]) == guess) {
weight &= w[i];
}
}
if (weight <= k) ans = guess;//该位可以为1
}
return ans;
}
static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in), 65535);
static StreamTokenizer st = new StreamTokenizer(bf);
static int I() throws IOException {
st.nextToken();
return (int) st.nval;
}
}