Description
小H和小Z正在玩一个取石子游戏。 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,
每次取石子的个数有限制,谁不能取石子时就会输掉游戏。 小H先进行操作,他想问你他是否有必胜策略,如果有
,第一步如何取石子。
Input
输入文件的第一行为石子的堆数N
接下来N行,每行一个数Ai,表示每堆石子的个数 接下来一行为每次取石子个数的种类数M
接下来M行,每行一个数Bi,表示每次可以取的石子个数,
输入保证这M个数按照递增顺序排列。
N≤10 Ai≤1000
对于全部数据,M≤10,Bi≤10
Output
输出文件第一行为“YES”或者“NO”,表示小H是否有必胜策略。
若结果为“YES”,则第二行包含两个数,第一个数表示从哪堆石子取,第二个数表示取多少个石子,
若有多种答案,取第一个数最小的答案,
若仍有多种答案,取第二个数最小的答案。
Sample Input
4
7
6
9
3
2
1
2
Sample Output
YES
1 1
Hint
样例中共有四堆石子,石子个数分别为7、6、9、3,每人每次可以从任何一堆石子中取出1个或者2个石子,小H有
必胜策略,事实上只要从第一堆石子中取一个石子即可。
HINT
思路:
由于数很小,而且每个堆都是独立的,所以我们可以暴力sg函数,
最后亦或和为 0 就是必败。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+100;
int a[N],b[N],sg[N];
bool vis[N];
int n,m,ans;
void get_sg(){ //sg函数。暴力sg函数。
for (int i = 1; i < 1005; i++){
memset(vis,0,sizeof(vis));
for (int j = 0; j < m && b[j] <= i; j++){
vis[sg[i - b[j]]] = 1;
}
for (int j = 0; j < 1006; j++)
if (vis[j] == 0) {
sg[i] = j;
break;
}
}
}
void init(){ //初始化,读入。
scanf("%d",&n);
for (int i = 0; i < n; i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (int i = 0; i < m; i++)
scanf("%d",&b[i]);
get_sg();
}
void solve(){
for (int i = 0; i < n; i++)
ans ^= sg[a[i]];
if (!ans) puts("NO"); else{
puts("YES");
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
if (b[j] <= a[i] && (ans ^ (sg[a[i]]) ^(sg[a[i] - b[j]])) == 0){
printf("%d %d\n",i + 1,b[j]);
return;
}
}
}
}
}
int main(){
init();
solve();
return 0;
}