题目描述:
1755 除数游戏
在除数游戏中,两人轮流行动,初始时有一个整数q,每次行动要写下一个整数,这个整数必须
是最近一次出现的整数的“强除数”。所谓一个整数的“强除数”是指除了1和该整数本身以外,可以
整除该整数的整数。
当游戏的某一方找不出符合以上条件的整数时,该方取得胜利,游戏结束。
假设游戏双方都采取最好的策略,给出初始数字。计算第一个写数字的人赢,还是第二个写数字
的人赢。
样例解释:
在样例一中,数字6的“强除数”是2和3。不管是写哪个数字,下一个人都赢了。
在样例二中,6是30的一个“强除数”。写下6后,接下来的过程同上。输入
单组测试数据。 第一行,有1个整数q(1≤q≤10^13) 表示初始数字。输出
共一行,如果第一个写数字的人赢,则输出1,否则输出2。输入样例
6 30输出样例
2 1
思路:
本题不难,但是想复杂的话容易漏掉 n==1 的情况。
刚开始想的是一般情况下只要能找到N的一个合数因子即第一人可赢,另外
或者N为素数也是第一人赢。其他情况一律第二人赢。但漏掉 N==1的情况。
其实除了N只有两个素数因子且相乘等于N的情况是第二人赢外,其余情况
都是第一人赢 。尝试写了一下代码突然发现按照划掉部分思路写还是需要几个特判,还不如之前的思路呢。
代码实现(刚开始的思路):
#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e5+100;
int fac[N],cnt;
int primeFac(LL x) {
int num=0;
for(LL i=2; i*i<=x; ++i) {
if(x%i==0) {
fac[++cnt]=i;
while(x%i==0)x/=i,num++;
}
}
if(x>1)num++,fac[++cnt]=x;
return num;
}
int main() {
LL n,ans;
int tot;
while(cin>>n) {
cnt=0;
ans=0;
tot=primeFac(n);
if(tot==1||tot==0) { //素数或者为1的情况
cout<<1<<endl;
} else {
//否则,找一个合数因子
for(LL i=2; i*i<=n; i++) {
if(n%i==0) {
if(primeFac(i)!=1) {
ans=i;
break;
}
if(primeFac(n/i)!=1) {
ans=n/i;
break;
}
}
}
if(ans) { //找到
cout<<1<<endl;
} else { //没找到
cout<<2<<endl;
}
}
}
return 0;
}
THE END;