编程之美-找符合条件的整数

原创 2012年03月29日 19:57:27

题目:

任意给定一个正整数N,求一个最小的正整数MM>1),使得N * M的十进制表示形式里只含有10

看了题目,我很自然的想到了枚举。然后看N * M的十进制是否只包含10。当然,这种暴力的解法不是我们想要的。

换一种枚举方法,我们枚举N*M的取值效果怎么样呢?因为N * M的只包含10,所以对于K位的N*M,需要搜索2K次方。

因为找的是最小整数,所以可以采用BFS(宽度优先搜索)。如果最终解使得N * Mk位,那么总共要搜索2的(k+1)次方。有什么方法可以剪枝么?

答案是肯定的。

N = 3时,看如下搜索树,括号内容表示mod N的值:


X = 101 Y=110,可知XY同余。

所以10X + 010Y + 0同余,10X + 110Y + 1同余,并且易知,从X继续往下搜索的值,一定比Y的小。要求最小的M,我们还有必要拓展Y节点么?

综上所述,采用BFS方法,在每一层中,如果出现余数相同的节点,只需要拓展最先出现的即可。


《编程之美》介绍的是另一种更妙的方法。

枚举M也好,BFS搜索N * M也好,我们有没有想过N * M超出整数范围?难道对于大整数,我们还要手写一个大数类?好麻烦…………


首先要解决的是,对于大整数,我们如果表示呢?

因为结果N * M只包含10,我们可以用一个vector保留1出现的位数。比如11001,可以用 {0 3 4} 表示。这种方法很省空间。

回想一下刚才提到的,BFS的剪枝方法——同余的数只保留最小的!

看个实例大家就好懂了:

如果知道100 mod 3 =1 

 10 mod 3 = 1

  1 mod 3 = 1

110 mod 3 = 2

如何找到比110更小而且mod 3 = 2的数呢?用1去替换110中的10OK了。因为110同余,所以保留余数最小的即可,毕竟我们找的是满足mod N = 0最小且只含有01的数。


我的代码如下:

#include <iostream>
#include <vector>
using namespace std;

void display(vector<int> &v)
{	
	int t = 0;
	for (int i = v.size() - 1;i >= 0;i--)
	{
		t = v[i];
		cout << '1';
		while(i > 0 && --t != v[i - 1])
			cout << '0'; 
	}
	while(t--)
		cout << '0';
	cout << endl;
}
void searchTheNum(vector<vector<int>> &v, int n)
{
	for (int i = 0;i < n;i++)
	{
		vector<int> nv;
		nv.clear();
		v.push_back(nv);
	}
	v[1].push_back(0);
	int j;
	for (int i = 1, j = 10 % n; ;i++, j = (j * 10) % n)
	{
		if (0 == v[j].size())
		{
			v[j].push_back(i);
		}
		for (int k = 0;k < v.size();k++)
		{
			if (v[k].size() > 0
				&& v[(k + j) % n].size() == 0
				&& i > v[k][v[k].size() - 1])
			{								
				v[(k + j) % n] = v[k];
				v[(k + j) % n].push_back(i);
			}
		}

		if (v[0].size())
		{
			display(v[0]);
			return;
		}
	}
}
int main()
{
	vector<vector<int>> v;
	int n = 99;
	searchTheNum(v, n);
	return 0;
}

对于书中的拓展问题1

对于任意的N,一定存在M,使得N*M的乘积的十进制表示只有01吗?

我百度到的答案是肯定存在,所以我的代码就假设一定存在解。

实际上书中的代码用了抽屉原理判断是否有解。


拓展问题2

怎么找出满足题目要求的和 M,使得N * M < 216次方,且N + M最大?

根据N定出M的上界,并在这个范围内进行查找。

用如上的思路都可以解决。

BFS:先拓展值较大的点,每层同余的数只保留值大的。

书中的方法:也是要保留大值。

这些都还要加上边界的判断。


参考资料:

《编程之美》 2.8 找符合条件的整数

http://www.cnblogs.com/bvbook/archive/2009/02/06/1385448.html 


编程之美——找符合条件的整数

转载自:http://blog.csdn.net/jcwKyl/article/details/3859155 。写的不错 题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十...
  • rein07
  • rein07
  • 2011年09月07日 08:49
  • 654

编程之美-找符合条件的整数

问题:任意给定一个正整数N,求一个最小的正整数M,使得N*M的十进制表示形式中只含有1和0, 先证明这样的M是存在的。         下面给出如何求解这样的M呢?代码中主要由find()函数...

编程之美2.8——找符合条件的整数

问题: 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。 解法: 由于没有直接的数学方法能帮我们直接得到M的值,所以我们只能进行搜索。由于...

编程之美2.8找符合条件的整数

问题: 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。 思路: 建立模N的余数记录表,通过动态规划的思想找到相应的M; 例子:...

编程之美——2.8 找符合条件的整数

题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解决这个问题首先考虑对于任意的N,是否这样的M一定存在。可以证明,M是一定存在的,而且不唯...
  • wens07
  • wens07
  • 2011年08月21日 14:44
  • 676

编程之美2.8 找符合条件的整数

//题目:给定一个数N,求另一最小数M使得N*M为只由0和1构成的数 //解法1:让M从1开始与N相乘,判断相乘的结果是否只由1和0组成(复杂度高) //解法2:把问题转化为:求最小的只由0,1组成的...

编程之美:第二章 数字之魅 2.8找到符合条件的整数

/* 找到符合条件的整数: 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0 首先想到从小到大枚举M的取值,然后计算N*M,最后判断他们的乘积是否只含有...

找符合条件的数(编程之美)

任意一正整数 N,求一个最小的正整数 M(M > 1),使得 N * M 的十进制表示式里只有 1 和 0 . 分析: 对于正整数 N = 7 ,只需依次取值如 X X               1...

找符合条件的整数

任意给定一个正整数N,求一个最小的正整数M(M >1),使得N * M的十进制表示形式里只含有1和0。 解法1: 看了题目要求之后,我们的第一想法就是从小到大枚举M的取值,然后再计算N *...

《编程之美》 符合条件的数

证明存在:http://blog.csdn.net/jcwKyl/article/details/3859155 自己的代码 M取余数能算的数比较大:int _tmain(int argc, _TC...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编程之美-找符合条件的整数
举报原因:
原因补充:

(最多只允许输入30个字)