POJ 1426 Find The Multiple (寻找倍数)

题目链接:POJ 1426

题意:

给一个正数n找出一个n的倍数,并且这个倍数各个位上的数字不是0就是1。

如果有多种答案,输出一个即可。

分析:

首先想到了大数乘法,由于要保证每个位上的数字非0即1,那么由n的最后一位不为0的数就可以限制乘数。例如n最后一位不为0的数如果是1,那么乘数的最后一位只能是1(如果是其他数字那么相乘得到的数最后一位一定不满足非0即1)【0除外,相当于*10了,没意义】

于是写出了如下代码:

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 105;
char p[105], ans[105], tmp[maxn];
int carry, k, t, r;

int valid(char s[])
{
for (int i = 0;s[i];i++)
if (!(s[i] == '0' || s[i] == '1')) return 0;
return 1;
}

void reverse(char s[])
{
int lens = strlen(s);
for (int i = 0;i < lens / 2;i++)
{
char c1 = s[i];
s[i] = s[lens - 1 - i];
s[lens - 1 - i] = c1;
}
}

void mul(char a[], char b[], char d[])
{
reverse(a);
reverse(b);
int lena = strlen(a);
int lenb = strlen(b);
int i, j;
j = carry = 0;
for (int p = 0;p < lena + lenb - 1;p++)
d[p] = '0';
while (b[j])
{
for (i = 0;i <lena;i++)
{
int t = (a[i] - '0') * (b[j] - '0') + carry + d[i + j] - '0';
carry = t / 10;
t %= 10;
d[i + j] = t + '0';
}
j++;
}
k = lena + lenb - 1;
d[k++] = carry + '0';
d[k] = '\0';
reverse(d);
while (d[0] == '0'&&strlen(d)>1)//清楚前缀0
{
int i;
for (i = 0;i < (strlen(d) - 1);i++)
d[i] = d[i + 1];
d[i] = '\0';
}
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
while (~scanf("%s",p))
{
if (strcmp(p, "0") == 0) break;
if (valid(p))
{
puts(p);
continue;
}
int len = strlen(p);
for (int i = len - 1;;i--)
{
if (p[i] != '0')
{
t = p[i] - '0';
break;
}
}
if (t == 1) r = 11;
else if (t == 2) r = 5;
else if (t == 3) r = 7;
else if (t == 4) r = 5;
else if (t == 5) r = 2;
else if (t == 6) r = 5;
else if (t == 7) r = 3;
else if (t == 8) r = 5;
else if (t == 9) r = 9;
for (int i = r;;i += 10)
{
sprintf(tmp, "%d", i);
mul(tmp, p, ans);
if (valid(ans)) break;
}
puts(ans);
}
return 0;
}

但是TLE了!到网上找到了一种解题报告的思路:

用BFS搜索,首先从1开始,那么下一个入队列的是1*10和1*10+1,依此类推,代码很简洁。

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
long long ans,cur;
int n;
long long bfs(int  n)
{
	queue<long long> q;
	q.push(1);
	while(1)
	{
		cur=q.front();
		q.pop();
		if (cur%n == 0) return cur;
		q.push(cur * 10);
		q.push(cur * 10+1);
	}
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	while (cin>>n)
	{
		if (n == 0) break;
		ans = bfs(n);
		cout << ans << endl;
	}
	return 0;
}
但是依然TLE!!!

又看到一种用DFS的方法,想法一样。

需要注意的是:

①一层递归相当于位数加一,而long long型最多存储19位,多了就不行了,所以递归时要传递一个参数,当==20时,回溯。

②设置一个bool类型,用以标记是否找到正确的倍数。

代码如下:

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

long long ans, cur;
int n;
bool flag;
void dfs(int k,long long t)
{
	if (flag) return;
	if (k == 20) return;
	if (t%n == 0)
	{
		flag = true;
		cout << t << endl;
		return;
	}
	dfs(k + 1, t * 10);
	dfs(k + 1, t * 10 + 1);
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	while (cin >> n)
	{
		if (n == 0) break;
		flag = false;
		dfs(1, 1);
	}
	return 0;
}
这样子就AC了!可真是神奇啊~我说怪不得测试样例6和19给的Output结果是

100100100100100100
111111111111111111
DFS做出来的也是这个结果,而BFS做出来的是

1110
11001
!!!!!
o(╯□╰)o


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值