這道題我想吐槽的是,臥槽爲什麼我的第一種方法竟然可以AC,這也太不嚴謹了。
題目概述:
這道題是說給定一個1-200之間的數n,在他的倍數中找到一個數,這個數的要求是所有位數只爲0或者1,輸出這個數。
算法思想:
開始想的是枚舉每個倍數,然後每個倍數去檢測是不是0還是1,覺得臥槽肯定越界,肯定越界,肯定越界,然後就又想了一下沒想出來就去看解題報告了。
嗯然後看到第一種方法,是用BFS枚舉0和1,然後每次得到數字之後都mod一下n看能不能整除。
坑的地方就在於在long long範圍內,這個方法竟然能夠實現,也就是說所有結果的倍數沒有一個超過18位的,這跟題目描述的幾百位不同呀少年。
好了這個方法很好理解。我把代碼放在這裏,然後值得看的應該是下面的一個代碼。
代碼部分:
#include <iostream> #include <queue> using namespace std; int n; void bfs() { queue<long long> q; q.push(1); long long x = 1, pos; while (!q.empty()) { pos = q.front(); q.pop(); x = pos * 10; if (x % n == 0) { cout << x << endl; break; } q.push(x); x++; if (x % n == 0){ cout << x << endl; break; } q.push(x); } } int main() { while (cin >> n && n != 0) { if (n == 1) { cout << n << endl; continue; } bfs(); } return 0; }
真正值得看的代碼:
這個用到了同餘模定理,簡單的來說就是mod這個符號可以“亂加”。是厲害。
http://user.qzone.qq.com/289065406/blog/1303946967
//Memory Time //2236K 32MS #include<iostream> using namespace std; int mod[524286]; //保存每次mod n的餘數 //由於198的餘數序列是最長的 //經過反覆二分驗證,436905是能存儲198餘數序列的最少空間 //但POJ肯定又越界測試了...524286是AC的最低下限,不然鐵定RE int main(int i) { int n; while(cin>>n) { if(!n) break; mod[1]=1%n; //初始化,n倍數的最高位必是1 for(i=2;mod[i-1]!=0;i++) //利用同餘模定理,從前一步的餘數mod[i/2]得到下一步的餘數mod[i] mod[i]=(mod[i/2]*10+i%2)%n; //mod[i/2]*10+i%2模擬了BFS的雙入口搜索 //當i爲偶數時,+0,即取當前位數字爲0 。爲奇數時,則+1,即取當前位數字爲1 i--; int pm=0; while(i) { mod[pm++]=i%2; //把*10操作轉化爲%2操作,逆向求倍數的每一位數字 i/=2; } while(pm) cout<<mod[--pm]; //倒序輸出 cout<<endl; } return 0; }