POJ 1426 Find The Multiple【题解报告|DFS|BFS|模运算】

题目大意

给出一个整数 n ( 1 < = n < = 200 ) n (1 <= n <= 200) n(1<=n<=200)

求出任意一个它的倍数m,要求m必须只由十进制的 0 或 1 组成。

思路分析

首先暴力枚举肯定是不可能的 1000ms 想不超时都难,而且枚举还要解决大数问题。

解题方法: BFS|DFS+同余模定理


我以 n = 6 n=6 n=6 为例

首先十进制数,开头第一个数字(最高位)一定不能为0,即最高位必为 1

设6的 “01十进制倍数” 为k,那么必有 k % 6 = 0 k\%6 = 0 k%6=0 ,现在就是要用 B F S ∣ D F S BFS|DFS BFSDFS求k值:

1、先搜索 k k k的最高位,最高位必为1,则此时 k=1,但 1%6 = 1 != 0
 因此 k=1 不是所求,存储余数 1

2、搜索下一位,此时有两种可能:
  下一位可能为 0,即 k ∗ 10 + 0 k*10+0 k10+0,此时 k = 10 k=10 k=10,那么 k % 6 = 4 k\%6=4 k%6=4
  可能为 1,即 k ∗ 10 + 1 k*10+1 k10+1,此时 k = 11 k=11 k=11,那么 k % 6 = 5 k\%6=5 k%6=5
 由于余数均不为0,即 k = 10 k=10 k=10 k = 11 k=11 k=11 均不是所求

3、继续搜索第三位,此时有四种可能了:
 对于 k=10,
  下一位可能为0,即 k*10+0,此时 k=100,那么 k%6=4
  下一位可能为1,即 k*10+1,此时 k=101,那么 k%6=5
 对于k=11,
  下一位可能为0,即 k*10+0,此时 k=110,那么 k%6=2
  下一位可能为1,即 k*10+1,此时 k=111,那么 k%6=3
 由于余数均不为0,即 k=100,k=101,k=110,k=111 均不是所求

4、继续搜索第四位,此时有八种可能了:
 对于k=100,
  下一位可能为0,即 k*10+0,此时 k=1000,那么 k%6=4
  下一位可能为1,即 k*10+1,此时 k=1001,那么 k%6=5
 对于k=101,
  下一位可能为0,即 k*10+0,此时 k=1010,那么 k%6=2
  下一位可能为1,即 k*10+1,此时 k=1011,那么 k%6=3
 对于k=110,
  下一位可能为0,即 k*10+0,此时 k=1100,那么 k%6=2
  下一位可能为1,即 k*10+1,此时 k=1101,那么 k%6=3
 对于k=111,
  下一位可能为0,即 k*10+0,此时 k=1110,那么 k%6=0
  下一位可能为1,即 k*10+1,此时 k=1111,那么 k%6=1
 我们发现 k=1110 时,k%6=0,即 1110 就是所求的倍数

从上面的演绎不难发现,用BFS是搜索 当前位数字 (除最高位固定为1),因为每一位都只有0或1两种选择,换而言之是一个双入口BFS,当然这道题没有让我们求位数最少的,因此我们也可以使用带深度约束的dfs进行操作,dfs的实现更简便一些。

dfs:

//164K	313MS	
int n;
string t, res;

bool dfs(int mod) {
	if (t.size() > 100)return false;//有深度限制的dfs
	else if (mod == 0) { res = t; return true; }

	t += '0';
	if(dfs((mod * 10) % n))
		return true;
	t.erase(t.size() - 1, 1);
	t += '1';
	if(dfs((mod * 10 + 1) % n))
		return true;
	t.erase(t.size() - 1, 1);
	return false;
}

int main() {
	while (scanf("%d", &n) && n) {
		t.clear(); res.clear();
		t += '1';
		dfs(1);
		cout << res << endl;
	}
}

bfs:

//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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值