#include<stdio.h>
#include<iostream>
using namespace std;
bool flag;
bool check(int big,int small,int n)
{
int i;
for(i=n;i>1;i--)
{
if(small%i==0){
if(check(big,small/i,i-1))return true;
}
if(big%i==0){
if(check(big/i,small,i-1))return true;
}
}
if(small == 1){ //分數少者有可能沒有說謊
flag = true;
}
else if(!flag){ //如果分少的說謊了(包含了分數多者說謊的情況)
return true;
}
if(big==1&&small==1){ //兩個人的分數相容
return true;
}
return false; //得分少者的分數能被分解結束了,但是得分大不能被分解,返回上一層繼續搜索相容的情況
}
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
int big,small;
flag = false;
big = a>b?a:b;
small = a>b?b:a;
int win=big;
if(!check(big,small,100))
{
win=small;
}
printf("%d\n",win);
}
return 0;
}
(1)爲什麼這樣做呢?由於情況有很多種,如果你要用數組記錄所有的可能的情況,至少得開一個100*100的二維數組,還有可能就是給出的數字很大,進行因式分解是不好處理的,應爲這個題目要求的數字絕對不能出現兩個相同數字的乘積。如果求出兩個所有可能的情況,進行比兌,但是這種思想實在不知道怎麼樣操作。一種辦法就是用nlog(n)的方法進行解的搜索。如果找到一個這兩個數的兩種可能的分解方案,就進行判定,這兩個方案是否相容,如果相容則可以得出結果;如果不相容,繼續找相容的情況了。算法的時間複雜度是(nLog(n))。這個題目需要想清楚的地方就是,如果判斷解是否相容。判斷解相容有下列幾種情況:
1》如果小的數字到一,可以認爲小的沒有撒謊。此時要判定大的分數是否被整除到一。如果大的被整除到一,說明這種情況下,這兩個分數是相容的,判定大的贏;如果沒有被整除到一,顯然大的在說謊,此時由於不知道小的是否在說謊,所以返回上一層,再進行判斷,找有沒有跟大的分數相容的情況,如果有,就判斷大的贏,顯然這種情況是不存在的,可以直接判斷小的贏,這裏存在一個剪枝,但是在程序中沒有體現出來。
2》如果小的數字沒到一。顯然說謊了,那麼就判定分數大的贏了;
(2)這個方法還有說明改進的地方?
(3)還有沒有其他的方法呢?