「一本通 6.7 练习 1」取石子游戏
题目描述
小H和小Z正在玩一个取石子游戏。 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏。 小H先进行操作,他想问你他是否有必胜策略,如果有,第一步如何取石子。
输入
输入文件的第一行为石子的堆数
N
N
N
接下来
N
N
N 行,每行一个数
A
i
A_i
Ai,表示每堆石子的个数,接下来一行为每次取石子个数的种类数
M
M
M
接下来
M
M
M 行,每行一个数
B
i
B_i
Bi,表示每次可以取的石子个数,
输入保证这
M
M
M 个数按照递增顺序排列。
输出
输出文件第一行为 YES
或者 NO
,表示小H是否有必胜策略。
若结果为 YES
,则第二行包含两个数,第一个数表示从哪堆石子取,第二个数表示取多少个石子,
若有多种答案,取第一个数最小的答案,
若仍有多种答案,取第二个数最小的答案。
样例输入
4
7
6
9
3
2
1
2
样例输出
YES
1 1
提示
对于全部数据, M ≤ 10 , N ≤ 10 , A i ≤ 1000 , B i ≤ 10 M≤10,N≤10,A_i≤1000,B_i≤10 M≤10,N≤10,Ai≤1000,Bi≤10
Code
#include <bits/stdc++.h>
using namespace std;
int n, m, a[15], b[15], vis[1005], f[1005];
void in()
{
cin >> n;
for (int i(1); i <= n; ++i)
scanf("%d", &a[i]);
cin >> m;
for (int i(1); i <= m; ++i)
scanf("%d", &b[i]);
}
void init()
{
for (int i(1); i <= 1000; ++i)
{
for (int j(1); j <= m && b[j] <= i; ++j)
vis[f[i - b[j]]] = i;
while (vis[f[i]] == i)
++f[i];
}
}
int main()
{
in();
init();
for (int i(1); i <= n; ++i)
for (int j(1); j <= m && b[j] <= a[i]; ++j)
{
a[i] -= b[j];
int sum(0);
for (int k(1); k <= n; ++k)
sum ^= f[a[k]];
if (!sum)
{
puts("YES");
cout << i << " " << b[j];
return 0;
}
a[i] += b[j];
}
puts("NO");
}
广告
绿树公司 - 官方网站:https://wangping-lvshu.github.io/LvshuNew/
绿树智能 - 官方网站:https://wangping-lvshu.github.io/LvshuZhineng/
(现在使用,人人均可获得300元大奖)