Number Game - 记忆化搜索+ 递推求博弈论
Posted emcikem
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Number Game - 记忆化搜索+ 递推求博弈论相关的知识,希望对你有一定的参考价值。
传送门
以前博弈论都是靠找规律,这个题给我了新的思路,就是如果说博弈论里面的操作是对数字操作,那么可以采用递推的形式
先初始化(sqrt(n))的数据,然后有种杜教筛的思想,对于(n > N)时,才回去继续查找,而在求dp[n / j]时,继续查看,n / j 是否 < N
设dp[i], 如果dp[i] = 1,表示i这个数字是先手必胜,2则为后手必胜
本题就是如果说n是一个除了1外的奇数,直接除以本身即可,那么就是先手胜利,否则,对于偶数来说
(sqrt(n))找自己的所有因子,如果说除以因子后的dp是2,表示我操作后的值是后手必胜,那么我可以赢。最后默认为2。
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5 + 5;
int dp[N];
void init(int n){//初始化
dp[1] = 2; dp[2] = dp[3] = 1; dp[4] = 2; dp[5] = 1; dp[6] = 2;
for(int i = 7; i <= n; i++){
if(dp[i - 1] == 2 || i % 2 == 1) {//我减去1后为后手必胜,或者为奇数,则我先手必胜
dp[i] = 1;
continue;
}
for(int j = 2; j * j <= i; j++){//偶数进行查找
if(i % j == 0){
if(dp[i / j] == 2 && j & 1) {
dp[i] = 1;
break;
}
if(j * j != i && (i / j) & 1 && dp[j] == 2){
dp[i] = 1;
break;
}
}
}
if(!dp[i]) dp[i] = 2;//默认值
}
}
int cal(int n){//杜教筛思想的搜索
if(n < N - 2) return dp[n];
if(n & 1) return 1;
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
if(cal(n / i) == 2 && i & 1)
return 1;
if(i * i != n && (n / i) & 1 && cal(i) == 2)
return 1;
}
}
return 2;
}
int main(){
init(N - 2);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
if(cal(n) == 1) printf("Ashishgup
");
else printf("FastestFinger
");
}
return 0;
}
以上是关于Number Game - 记忆化搜索+ 递推求博弈论的主要内容,如果未能解决你的问题,请参考以下文章
B2. Palindrome Game (hard version)(记忆化搜索)