看到博弈就懵逼的我><这一题原来是递归做。
如果当前player接手数字N,该方一定赢的条件是存在一种prime factor的选择方法,使得另一方一定会输。
如果当前player接手数字N,该方一定输的条件是没有一种prime factor的选择方法,使得另一方一定会输。i.e., 如果存在一种策略使得另一方一定会输,那么当前player一定不会输。
这样就可以枚举所有的prime factor选择方法,递归处理。
看到N=1e15吓cry了。事实上,前14个质数(2,3,5,7,...so on)相乘就已经超过1e15了,所以N对应的质因子个数不会很多,所以递归层数不会很多。
以及学到了一种神奇的筛质因子的方法。╮(╯▽╰)╭
开始大数据dead了是因为枚举质因子的循环里把long long写成了int。可能因为int溢出变成负数了,循环就出不来了。o(╯□╰)o
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
//2016 Round B Problem C. gNumbers
int T;
const int maxn=2010;
long long N;
bool ans;
vector<long long>factors;
bool isprime(long long num)
{
for(long long i=2;i*i<=num;i++)
{
if(i==num) continue;
if(num%i==0)
{
return false;
}
}
return true;
}
bool isgnumber(long long num)
{
// if(num==1)
// {
// return true;must return true if num==1
// }
long long sum=0;
while(num>0)
{
sum+=num%10;
num/=10;
}
return isprime(sum);
}
bool win(long long num);
bool lose(long long num)//whether the player handling num must lose, true is mustlose
{
//cout<<"lose "<<num<<endl;
if(isgnumber(num)==true)
{
return true;
}
long long tmpnum=num;
for(int i=0;i<factors.size();i++)
{
if(num%factors[i]==0&&isprime(factors[i])==true)//
{
long long tmpnum=num;
while(tmpnum%factors[i]==0)
{
tmpnum/=factors[i];
}
if(win(tmpnum)==false)
{
return false;
}
}
}
return true;
}
bool win(long long num)//whether the player handling num will win, true is must win
{
//cout<<"win "<<num<<endl;
if(isgnumber(num)==true)
{
return false;
}
for(int i=0;i<factors.size();i++)
{
if(num%factors[i]==0&&isprime(factors[i])==true)//tmpnum%factors[i] leads to WA
{
long long tmpnum=num;
while(tmpnum%factors[i]==0)
{
tmpnum/=factors[i];
}
if(lose(tmpnum)==true)
{
return true;
}
}
}
return false;
}
int main()
{
// long long prod=1;
// int cnt=0;
// for(long long i=2;i<45;i++)
// {
// if(isprime(i))
// {
// cnt++;
// prod*=i;
// }
// }
// cout<<cnt<<" "<<prod<<endl;
// return 0;
freopen("C-small-practice.in","r",stdin);
// freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
factors.clear();
scanf("%lld",&N);
long long tmp=N;
for(long long i=2;i*i<=tmp;i++)//use int i leads to dead loop in large dataset
{
if(tmp%i==0)
{
factors.push_back(i);
while(tmp%i==0)
{
tmp/=i;
}
//cout<<i<<" "<<tmp<<endl;
}
}
if(tmp>1)
{
factors.push_back(tmp);
}
ans=win(N);
printf("Case #%d: %s\n",ca,(ans==true?"Laurence":"Seymour"));
}
return 0;
}
本文探讨了一种基于递归策略解决博弈问题的方法,并通过筛选质数因子来判断玩家是否能赢得游戏。针对数字N,文章详细介绍了如何利用递归算法来确定获胜策略。


被折叠的 条评论
为什么被折叠?



