A - The Artful Expedient
题目大意:
一对基友在玩♂游♂戏♂。每个人有一个数列,两个数列中所有的数字都不一样。
规则是,在两个数列中各取出一个数(a,b),将所有不同的数对全部取出来。
计算 a^b ,如果得到的值在两个数列其中的一个里,那么就加一分。
结束后计算得分,如果是奇数,则是Koyomi获胜,偶数则是Karen获胜。
输入一行一个整数:代表每个人有n个数。n ∈ [1,2000]。
输入一行n 个整数:代表Koyomi的数列。数列中数字的范围是[1,2e6]。
输入一行n 个整数:代表Karen的数列。数列中数字的范围是[1,2e6]。
输出一个字符串:代表胜利者。
样例输入:3 5
1 2 3 2 4 6 8 10
4 5 6 9 7 5 3 1
样例输出:Karen Karen
解题思路:
此题可以用暴力求解,但是却又更加优美的过题方式,利用异或运算的规律即可。
在异或运算中,若存在 a ^ b = c 那么也一定存在 a ^ c = b 以及 b ^ c = a。就像是一个环一样。
那么假设两个数列为 x,y。若a在x中,b在y中,且a ^ b = c,c在x或y中。
那么遍历x时,运算到a的时候,得到一分,运算到c的时候又得到了一分。
所以一旦有符合条件的情况出现,那么必定是成对出现的。
所以一定有偶数的分数,Karen一定胜利。
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 for(int i = 0;i < n;i ++){ 9 int t = sc.nextInt(); 10 } 11 for(int i = 0;i < n;i ++){ 12 int t = sc.nextInt(); 13 } 14 System.out.println("Karen"); 15 } 16 } 17 }
B - The Eternal Immortality
题目大意:
给你两个数a,b(a <= b && a,b ∈ [0,1e18])。
求出(b!/a!)的个位数字。
输入一行两个整数:a,b。
输出一行一个整数:代表(b!/a!)的个位数字。
样例:2 4 --> 2
0 10 --> 0
107 109 --> 2
解题思路:
明显要进行 %10 的处理。
而且结果跟两个数字的差有关。
但是部分人可能只想到了如果差大于十,结果都是0。
其实仔细想一下,两个数的差只要大于5,个位数就已经一直是0了。
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 long x = sc.nextLong(); 8 long y = sc.nextLong(); 9 long t = y - x; 10 long ans = 1; 11 if(t >= 5){System.out.println("0");} 12 else{ 13 while(t > 0){ 14 ans = ans * (y % 10); 15 y --; 16 t --; 17 } 18 System.out.println(ans % 10); 19 } 20 } 21 } 22 }
C - The Intriguing Obsession
题目大意:
有三个群岛(姑且称为红岛,蓝岛,紫岛),每个群岛有若干个小岛。现在要在小岛之间造桥,每个桥的长度均为1。
相同颜色的小岛之间的距离至少为三或不相连。求解方案总数(对998244353取模)。
输入一行三个整数:a,b,c(a,b,c ∈ [1,5000])代表三个群岛(红蓝紫)的小岛数量。
输出一行一个整数:代表求解出的方案总数。
样例:1 1 1 --> 8
1 2 2 --> 63
1 3 5 --> 3264
6 2 9 --> 813023575
解题思路:
本题主要考察对于组合数的计算能力。
使用二维数组存放组合数。
因为两个群岛之间,能造的桥的数量最多是较少附属岛屿的数量。
所以独立求解ab,ac,bc三个方案个数,并将三个数相乘取模即可。
易推出任意两个岛屿之间的方案总数公式:
设两个岛屿群岛数量分别为 x,y(y <= x);
设任选k座桥(k ∈ [0,y]);
y群岛的方案共有 C(k,y);
对于x群岛,先拿出一座桥和y连上,有x个方案,再拿出一座桥继续连接,就只剩下(x - 1)个方案......
所以x群岛的所有方案应为(x)*(x - 1)*...*(x - k + 1),这其实就是A(k,x)种方案啦。
所以在本次条件下,所求的方案数量为:Σ(k ∈ [0,y])(C(k,y) * A(k,x))。
由于要求出C(a,b),C(a,c),C(b,c),所以必须满足a,b,c从大到小排列。
最后使用以上思路将三组结果求出使用同余模定理乘一下就好啦。
A C 代码:
1 import java.util.*; 2 3 public class Main{ 4 5 static long a = 0L; 6 static long b = 0L; 7 static long c = 0L; 8 static long modulo = 998244353; 9 static long C[][] = new long[5005][5005]; 10 static void init(){ 11 C[0][0] = 1; 12 for (int i = 1;i <= 5000;i ++){ 13 C[i][0]= 1; 14 for (int j = 1;j <= i;j ++){ 15 C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; 16 C[i][j] = C[i][j] % modulo; 17 } 18 } 19 } 20 public static void main(String[] args){ 21 init(); 22 Scanner sc = new Scanner(System.in); 23 while(sc.hasNext()){ 24 a = sc.nextLong(); 25 b = sc.nextLong(); 26 c = sc.nextLong(); 27 if(a < b){long t = a;a = b;b = t;} 28 if(a < c){long t = a;a = c;c = t;} 29 if(b < c){long t = c;c = b;b = t;} 30 long tab = 1L; 31 long tac = 1L; 32 long tbc = 1L; 33 long t = 1L; 34 for(long i = a;i >= a - b + 1;i --){ 35 t = t * i; 36 t = t % modulo; 37 tab = tab + t * C[(int)b][(int)(a - i + 1)]; 38 //System.out.println("tab = " + tab); 39 tab = tab % modulo; 40 } 41 t = 1L; 42 for(long i = a;i >= a - c + 1;i --){ 43 t = t * i; 44 t = t % modulo; 45 tac = tac + t * C[(int)c][(int)(a - i + 1)]; 46 //System.out.println("tac = " + tac); 47 tac = tac % modulo; 48 } 49 t = 1L; 50 for(long i = b;i >= b - c + 1;i --){ 51 t = t * i; 52 t = t % modulo; 53 tbc = tbc + t * C[(int)c][(int)(b - i + 1)]; 54 //System.out.println("tbc = " + tbc); 55 tbc = tbc % modulo; 56 } 57 long ans = (((tab * tac) % modulo) * tbc) % modulo; 58 System.out.println(ans); 59 } 60 } 61 }