1. 程式人生 > >POJ 1426 -- Find The Multiple

POJ 1426 -- Find The Multiple

二叉搜索樹 center pan include false esp while 搜索 amp

POJ 1426 -- Find The Multiple

大致題意:

給出一個整數n,(1 <= n <= 200)。求出任意一個它的倍數m,要求m必須只由十進制的‘0‘或‘1‘組成。

解題思路:

使用BFS,枚舉由0和1組成的數,判斷其是否為n的倍數

n的取值範圍為:1 <= n <= 200

最高位一定是1,二叉搜索樹如下所示:

技術分享圖片

我們使用數組存儲每一次的枚舉值(0或1),以上是n=6的情況,

題目提到:The decimal representation of m must not contain more than 100 digits.輸出的n的倍數會達到100位

隨著n的增大被除數會出現大數的情況,

為解決運算過程中出現大數

可利用 同余模定理 對得到余數的方式進行一個優化

(a*b)%n = (a%n *b%n)%n

(a+b)%n = (a%n +b%n)%n

相應的搜索樹可以改為:

技術分享圖片

所以,我們只要把每次進行除法運算得到的余數存儲下來就行,使用數組mod進行存儲

而n在200的範圍內, 余數值不可能超過3位數, 這就解決了 大數的問題

同時,要在搜索過程中進行剪枝,我們要尋找余數為0的結點,像下圖中黃色的結點為余數重復出現的結點,所以,應進行剪枝。

技術分享圖片

這樣進行剪枝之後,只有余數不同的才會進行處理,將最終的節點數也控制在了200(與余數的個數相同)。

 1 #include<iostream>
 2
#include<cstring> 3 using namespace std; 4 const int maxn = 200+10;///余數的最大個數 5 6 struct node{ 7 int num; 8 int par;//父親節點的下標 9 }; 10 node boolnum[maxn];//保存結果01十進制數 11 int mod[maxn];//與boolnum同步,保存每次的余數 12 bool visit[maxn];//記錄余數是否已經出現過 13 int ans[maxn]; 14 int n; 15 int bfs() 16 { 17 memset(visit,false
,sizeof(visit)); 18 int head=0,rear=1; 19 boolnum[head].num = 1;///最高位一定為1 20 boolnum[head].par = -1;///根節點的父親記為-1 21 visit[1] = true; 22 mod[head] = 1; 23 while(head<rear) 24 { 25 int u; 26 for(int i=0;i<=1;i++) 27 { 28 u = (mod[head]*(10%n)+i)%n; 29 if(!visit[u])///當前余數沒有出現過 30 { 31 ///進行存儲 32 boolnum[rear].num = i; 33 boolnum[rear].par = head;///存儲父節點的下標 34 mod[rear] = u; 35 visit[u] = true; 36 if(u==0)///得到解 37 { 38 int dept = rear; 39 int temp = 0; 40 while(dept != -1) 41 { 42 ans[temp++] = boolnum[dept].num; 43 dept = boolnum[dept].par; 44 } 45 return temp;///返回答案的位數 46 } 47 rear++; 48 } 49 } 50 head++; 51 } 52 } 53 54 int main() 55 { 56 while(cin>>n && n) 57 { 58 int temp = bfs(); 59 for(int i=temp-1;i>=0;i--) 60 cout<<ans[i]; 61 cout<<endl; 62 } 63 return 0; 64 }

技術分享圖片

POJ 1426 -- Find The Multiple