POJ1426 倍數01 BFS(同餘模定理)


這道題我想吐槽的是,臥槽爲什麼我的第一種方法竟然可以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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章