Codeforces #439.Div.2

本文解析了三道算法竞赛题目,包括游戏策略分析、阶乘尾数计算及复杂组合问题,提供了详细的解题思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 }
View Code

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 }
View Code

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 }
View Code

 

 

 

转载于:https://www.cnblogs.com/love-fromAtoZ/p/7723083.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值