蓝桥杯 约数倍数选卡片

Posted 王宜鸣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯 约数倍数选卡片相关的知识,希望对你有一定的参考价值。

思路:

搜索、博弈论。

实现的时候一个剪枝是从较大的数开始选,因为较大的数约数或倍数少一些,搜索的层数少。

还可以预处理出每个数的约数和倍数,这样搜索的时候不用扫描所有的数。

实现:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string>
 5 #include <cstring>
 6 #include <sstream>
 7 #include <vector>
 8 #include <algorithm>
 9 using namespace std;
10 
11 const int MAXN = 105;
12 int a[MAXN], b[MAXN], m = 0;
13 vector<int> ok[MAXN];
14 
15 bool check(int x, int y)
16 {
17     int p = min(x, y);
18     int q = max(x, y);
19     return !(q % p);
20 }
21 
22 void init()
23 {
24     for (int i = 1; i < MAXN; i++)
25     {
26         if (a[i])
27         {
28             for (int j = 1; j < MAXN; j++)
29             {
30                 if (a[j] && check(i, j))
31                     ok[i].push_back(j);
32             }
33         }
34     }
35 }
36 
37 bool dfs(int last)
38 {
39     for (int i = ok[last].size() - 1; i >= 0; i--)
40     {
41         int tmp = ok[last][i];
42         if (a[tmp])
43         {
44             a[tmp]--;
45             bool res = dfs(tmp);
46             a[tmp]++;
47             if (!res)
48                 return true;
49         }
50     }
51     return false;
52 }
53 
54 int main()
55 {
56     string x;
57     int t;
58     stringstream s;
59     getline(cin, x);
60     s << x;
61     while (s >> t)  a[t]++;
62     init();
63     s.clear();
64     getline(cin, x);
65     s << x;
66     while (s >> b[m++]);
67     m--;
68     sort(b, b + m);
69     int * end = unique(b, b + m);
70     bool flag = true;
71     for (int i = 0; i < end - b; i++)
72     {
73         a[b[i]]--;
74         bool res = dfs(b[i]);
75         a[b[i]]++;
76         if (!res)
77         {
78             cout << b[i] << endl;
79             flag = false;
80             break;
81         }
82     }
83     if (flag)
84         cout << -1 << endl;
85     return 0;
86 }

总结:

 必败点:前一个选手将取胜的位置称为必败点。

 必胜点:下一个选手将取胜的位置称为必胜点。

 必胜点和必败点属性:

 (1)所有终结点是必败点。

 (2)从任何必胜点操作,至少有一种方法可以进入必败点。

 (3)无论如何操作,从必败点都只能进入必胜点。

 可以采用递归或递推实现。

 注意函数参数的值传递的过程。

 回溯的时候不要影响标记状态的全局变量,要及时归位。

 

以上是关于蓝桥杯 约数倍数选卡片的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯 公约数公倍数

算法笔记_184:历届试题 约数倍数选卡片(Java)

蓝桥杯真题最小公倍数

最后的挣扎--蓝桥杯Java2021B组题解

LQ0226 公约数公倍数 程序填空

蓝桥杯真题阶乘约数