Codeforces #441.Div.2
Posted 薛定谔的Submit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces #441.Div.2相关的知识,希望对你有一定的参考价值。
A - Trip For Meal
题目大意:
一个蹭饭的孩子有三个好朋友甲乙丙,他从甲的家里吃完饭后出发并在这三个人的家之间来回走。
每到一个朋友家里,朋友都会请他吃顿饭,每次他吃完饭走之后,朋友又会立刻弄好一顿饭等他下次来吃。
输入四行四个整数:n,a,b,c。n代表要吃几顿饭(从甲哪里出发时已经在甲家吃过一次)。a,b,c分别代表甲乙,甲丙以及乙丙家的距离。
输出一行一个整数:代表这个孩子需要走的最短路程。
数据范围:所有数据均 ∈[1,100]。
样例:3 2 3 1 --> 3
1 2 3 5 --> 0
解题思路:
单纯的判断,首先判断最短的一条路是不是在a和b之间,如果是,就只需要在这条路上一直蹭吃的。
若最短路是c,那么就先走一次a,b中的最短路,再在c上面徘徊。
A C 代码:
1 import java.util.*; 2 3 public class Main{ 4 5 public static void main(String[] args){ 6 Scanner sc = new Scanner(System.in); 7 while(sc.hasNext()){ 8 int n = sc.nextInt(); 9 int a = sc.nextInt(); 10 int b = sc.nextInt(); 11 int c = sc.nextInt(); 12 if(n == 1){System.out.println("0");continue;} 13 if(a <= b && a <= c){ 14 System.out.println(a * (n - 1)); 15 } 16 else if(b <= a && b <= c){ 17 System.out.println(b * (n - 1)); 18 } 19 else if(c <= a && c <= b){ 20 int ans = Math.min(a,b) + (n - 2) * c; 21 System.out.println(ans); 22 } 23 } 24 } 25 }
B - Divisiblity of Differences
题目大意:
在一组数中找出若干个对另一个数取模相等的数。
输入一行三个整数:n,k,m(2?≤?k?≤?n?≤?100?000, 1?≤?m?≤?100?000)。
n代表接下来的数列中数的个数。k代表恰好在数列n中取出数字的个数。对m取模。
输入一行n 个整数:代表数列n。数列中的数字 ∈[0,1e9]。
输出一行"Yes"或"No":代表是否能取出这些数字。
若第一行输出了"Yes",则再输出一行,代表被选出的数,数字用一个空格隔开,行末没有多余空格。
样例输入:3 2 3 3 3 3 4 3 5
1 8 4 1 8 4 2 7 7 7
样例输出:Yes No Yes
1 4 2 7 7
解题思路:
在输入的时候将所有的数字处理,全部对m取模,并存放在一个个“桶”中记录次数。
遍历这些“桶”,一但出现“桶”中的数字大于等于k,那么记录下这个模(modd),也就是“桶”的下标。
然后遍历整个数组,如果n[i] % m == modd 那么输出n[i]。直到输出了k个数后,换行结束。
A C 代码:
1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] args){ 5 Scanner sc = new Scanner(System.in); 6 while(sc.hasNext()){ 7 int n = sc.nextInt(); 8 int k = sc.nextInt(); 9 int m = sc.nextInt(); 10 int mod[] = new int[m]; 11 int num[] = new int[n]; 12 int sum = 0; 13 int modd = 0; 14 for(int i = 0;i < n;i ++){ 15 num[i] = sc.nextInt(); 16 mod[num[i] % m] ++; 17 } 18 int flag = 1; 19 for(int i = 0;i < m;i ++){ 20 if(mod[i] >= k){ 21 modd = i; 22 System.out.println("Yes"); 23 flag = 0; 24 break; 25 } 26 } 27 if(flag == 1){ 28 System.out.println("No"); 29 } 30 else{ 31 int f = 0; 32 for(int i = 0;i < n;i ++){ 33 if(num[i] % m == modd){ 34 sum ++; 35 if(f == 0){System.out.print(num[i]);f ++;} 36 else {System.out.print(" " + num[i]);} 37 } 38 if(sum == k){break;} 39 } 40 System.out.println(); 41 } 42 } 43 } 44 }
C - Classroom Watch
题目大意:
给一个正整数n,求出比他小的所有正整数并符合下面条件.
若 x0 < n,且 x0 + (x0所有位数数字之和) == n,则 x0 符合条件。
输入一行一个整数:n ∈ [1,1e9]。
输出一行一个整数:k,代表符合条件的整数个数。
若上一行输出的数字不是0,那么再输出k行k个整数,即从小到大排列的符合条件的数。
样例输入:21 20
样例输出:1 0
15
解题思路:
虽然n最多有10位,但是不难发现,所有位数数字和最多才90。
题目中已经明确了一个公式: n = k + (所有位数数字和)。
所以我们只需要循环 9 * (数字位数)次即可求出所有符合条件的数。
A C 代码:
1 import java.util.*; 2 3 public class Main{ 4 5 static int check(String x){ 6 int s = 0; 7 for(int i = 0;i < x.length();i ++){ 8 s = s + (x.charAt(i) - ‘0‘); 9 } 10 return s; 11 } 12 13 public static void main(String[] args){ 14 Scanner sc = new Scanner(System.in); 15 while(sc.hasNext()){ 16 int out[] = new int[100]; 17 int index = 0; 18 String _in = sc.nextLine(); 19 int temp = 9 * _in.length(); 20 int in = Integer.valueOf(_in); 21 for(int i = in - temp;i <= in;i ++){ 22 String t = String.valueOf(i); 23 int ans = check(t); 24 if(ans + i == in){ 25 out[index] = i; 26 index ++; 27 } 28 } 29 System.out.println(index); 30 for(int i = 0;i < index;i ++){ 31 System.out.println(out[i]); 32 } 33 } 34 } 35 }
D - Sorting the Coins
题目大意:
有一排硬币,假设正面朝上为 O(大写o),背面朝上为 X。
最开始硬币的状态都为 O 。
然后有人给你捣乱,每次翻过来一个状态是 O 的硬币(之前翻过来的硬币不会再翻回去),直到将所有硬币全部翻过来。
让你求出每次翻转后需要进行几次以下策略才能结束,策略数从0开始计算。
最开始刚把所有硬币摆放好时(都是 O),也要进行策略。
策略:
如果这组硬币前边都是 O,后边都是 X(诸如OOOO或XXXX也算结束条件),那么结束。
从左向右,如果当前(k)硬币状态是 X,并且下一个(k + 1)硬币状态是 O,那么就交换。
交换过后从(k + 1)继续直到这行硬币被遍历结束。
其他情况均保持不变。
当所有的硬币归位后(即策略结束后),策略继续加一。
输入一行一个整数:n ∈ [1,3e6],代表有n个硬币。
输出一行n 个整数:每个整数代表这次翻过来的是几号硬币。
样例输入:4 8
1 3 4 2 6 8 3 4 7 2 1 5
样例输出:1 2 3 2 1 1 2 2 3 4 3 4 5 1
解释样例:
第一组:
初始化:O O O O,无需进行策略,结束后策略次数加一,所以总共为 1。
第一次:X O O O,进行一次策略,结束后策略次数加一,所以总共为 2。
第二次:X O X O,进行两次策略,结束后策略次数加一,所以总共为 3。
第三次:X O X X,进行一次策略,结束后策略次数加一,所以总共为 2。
第四次:X X X X,无需进行策略,结束后策略次数加一,所以总共为 1。
解题思路:
主要思想其实就是我们熟知的冒泡排序。将状态为X的硬币向后冒泡。
模拟一下发现,每次翻转后进行的策略总次数就是将尾缀的所有X去掉后的X的数量。
所以问题变成了如何计算尾缀的X。
超时代码(Java):
1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] args){ 5 Scanner sc = new Scanner(System.in); 6 while(sc.hasNext()){ 7 int n = sc.nextInt(); 8 int m[] = new int[n]; 9 int coins[] = new int[n]; 10 for(int i = 0;i < n;i ++){ 11 m[i] = sc.nextInt(); 12 } 13 System.out.print("1"); 14 int tail = n; 15 int ans = 1; 16 for(int i = 0;i < n - 1;i ++){ 17 ans ++; 18 coins[m[i] - 1] ++; 19 while(coins[tail - 1] == 1){ 20 tail --; 21 ans --; 22 } 23 System.out.print(" " + ans); 24 } 25 System.out.println(" 1"); 26 } 27 } 28 }
A C 代码(C/C++):
其实两个代码是一样的,在我用Java交了3发超时之后,就用C写了一份一模一样的,然后直接过掉。
这个题目好像并没有对Java提供额外的时间。
1 #include <stdio.h> 2 3 int main() 4 { 5 int n; 6 while (scanf("%d",&n) != EOF) 7 { 8 int m[n] = {0}; 9 int coins[n] = {0}; 10 for(int i = 0;i < n;i ++){ 11 scanf("%d",&m[i]); 12 } 13 printf("1"); 14 int tail = n; 15 int ans = 1; 16 for(int i = 0;i < n - 1;i ++){ 17 ans ++; 18 coins[m[i] - 1] ++; 19 while(coins[tail - 1] == 1){ 20 tail --; 21 ans --; 22 } 23 printf(" %d",ans); 24 } 25 printf(" 1\n"); 26 } 27 return 0; 28 }
以上是关于Codeforces #441.Div.2的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #441 Div. 2题解
Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)
Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)
[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段