编程之美——读书心得 2.8找符合条件的整数

来源:互联网 发布:快速排序java 编辑:程序博客网 时间:2024/05/16 11:44

问题:任意给定一个正整数,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。

 

看了题目要求之后,我们的第一想法就是从小到大枚举M的取值,然后再计算N * M,最后判断它们的乘积是否只含有1和0。大体的思路可以用下面的伪代码来实现:

for(M = 2; ; M++)

{

    product = N * M;

    if(HasOnlyOneAndZero(product))

        output N, M, Product, and return;

}

但是问题很快就出现了,什么时候应该终止循环呢?这个循环会终止吗?即使能够终止,也许这个循环仍需要耗费太多的时间,比如N = 99时,M = 1 122 334 455 667 789,N * M = 111 111 111 111 111 111。

 

分析从这里开始:

我们要求得M,首先要证明M存在。

一、证明:M一定存在,而且不唯一。

100%N,101%N,102%N,...,10x%N....这是一个无穷数列,且数列中每一项取值范围都在[0,N-1]之。所以这个无穷数中间必定才能在循环节假设 s,t 均为正整数,且s<t  ,

10s%N = 10t%N    则 10t-s%N = 1  , t-s是N的循环节

(之前在哪看到的,我忘记了,不好意思。这里不是很懂)

二、求解M。

问题转换,由最初的暴力求解M使得N*M的乘积有1和0转换为===>求解最小的正整数X,使得X的十进制表示只有1和0,并且X被N整除。

X的取值:1,,1,11,100,101,110,111,1000,……

若X最终位为K位,则要循环搜索2^k次,所以寻找最小的X,使得X mod N ==0即可。

 

我插入一些关于取模定律的知识:

同余式:a,b对p取模,它们余数相同,记做 a ≡ b (mod p)

定律:若a≡b (% p),则对于任意的c,都有(a + c) ≡ (b + c) (%p);
            若a≡b (% p),则对于任意的c,都有(a * c) ≡ (b * c) (%p);

 

应用到这里,

  ∵1%3=1, 10%3=1;

∴1≡10%3 

所以,(1+100)%3≡(10+100)%3,即101%3≡110%3

所以,可以只计算同位数小的数值即可。x,10x,10x+1 同余

例如,1001与1010

设 X=10^k, 10^k %N =a

那么X为K+1 位时, X = 10^k +Y     (0<Y<10^k)

对Y搜索,将有2^k-1个数据。

 

那么可以这样处理(思想):把Y按照对N的余数分解,将搜索空间分成N-1个子空间。对于每一个子空间,只需判断其中最小元素加上10^k能否被N整除即可。

这样,搜索空间从2^k-1压缩至N-1维。(前提是前面的计算已保留了余数信息,并且把Y的搜索空间进行了分解,即X%N的各种可能)

 

然后,10^k与Y的取模结果想加,再%N,看是否有新余数产生。这一步需要循环N次,因为已经将Y分成了N租。那么总的部署为(K-1)*N步。(从根至叶子自顶向下,深度搜索余数信息的次数)

// 将搜索空间分过类的广度搜索,这样空间占用是O(N)而不是// 指数级。分类的原则是按照模N的余数分类 #define _CRT_SECURE_NO_WARNINGS 1#include <cstdio>#include <bitset>#include <vector>#include <queue>using namespace std;struct QNode {int v, r; // v is value, r is remainderQNode(int vv, int rr): v(vv), r(rr) {}QNode(): v(0), r(0) {}};int main() {int N;while(scanf("%d", &N) != EOF) {//bitset<N> bn;queue<QNode> q;q.push(QNode(1, 1));while(!q.empty()) {//bn.reset();vector<bool> bn(N, false);int s = q.size();while(s--) {QNode t = q.front();if(t.r == 0) {printf("n = %d, m = %d, n*m = %d/n", N, t.v/N, t.v);goto ok;}q.pop();if(!bn[t.r * 10 % N]) {    //注意这里bn[t.r * 10 % N] = true;q.push(QNode(t.v * 10, t.r * 10 % N));}if(!bn[(t.r * 10 + 1) % N]) {bn[(t.r * 10 + 1) % N] = true;q.push(QNode(t.v * 10 + 1, (t.r * 10 + 1) % N));}}}ok:;}return 0;}


参考信息:http://blog.csdn.net/jcwKyl/article/details/3859155

0 0