题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0.
解法:原问题转化为求一个最小的正整数X,使得X的十进制表示形式里只含有1和0,并且X被N整除。于是乎就成了遍历二进制整数一样遍历X的各个取值,但是如果X的最终结果又K位,则要循环搜索2K 次。因此,可以建立一个长度为N的“余数信息数组”,这个数组的第i位保留已经出现的最小的模N为i的X。用BigInt[i]可能很大,只须记下1的位置即可。
1 for(i=0;i<N;i++) 2 BigInt[i].clear(); 3 BigInt[1].push_back(0); 4 5 int NoUpdate = 0; 6 //i 表示当前最高位是 10^i 次方 j表示 10^i % N的值 100 % N = ((10 % N) * 10) % N 注意 j避免表示大数的方法 7 for(i=1,j=10%N; ; i++,j=(j*10)%N) 8 { 9 bool flag = false; 10 if(BigInt[j].size()==0) 11 { 12 flag=true; 13 //BigInt[j]=10^i,(10^i %N =j) 14 BigInt[j].clear(); 15 BigInt[j].push_back(i); 16 } 17 for(k=1;k<N;k++) 18 { 19 if((BigInt[k].size()>0)&&(i>BigInt[k][BigInt[k].size()-1])&&(BigInt[(k+j)%N].size()==0)) 20 { 21 //(i>BigInt[k][BigInt[k].size()-1])说明当前的余数不是因为在i循环时由早些的k循环处理中产生的 22 //BigInt[(k+j)%N]=10^i+BigInt[k] 23 flag=true; 24 BigInt[(k+j)%N] = BigInt[k]; 25 BigInt[(k+j)%N].push_back(i); 26 } 27 } 28 if(flag==false) NoUpdate++; 29 else NoUpdate=0; 30 //如果经过一个循环节都没能对BigInt进行更新,就是无解,跳出。或者BigInt[0]!=NULL,已经找到解,也跳出 31 if(NoUpdate==N||BigInt[0].size()>0) 32 break; 33 } 34 if(BigInt[0].size()==0) 35 { 36 // M not exist; 37 } 38 else 39 { 40 //Find N*M=BigInt[0] 41 }
网上一个证明这M一定存在的思想:
解决这个问题首先考虑对于任意的N,是否这样的M一定存在。可以证明,M是一定存在的,而且不唯一。
简单证明:因为
这是一个无穷数列,但是数列中的每一项取值范围都在[0, N-1]之间。所以这个无穷数列中间必定存在循环节。即假设有s,t均是正整数,且s<t,有 。于是循环节长度为t-s。于是10^s = 10^t。因此有:
,所以
时间: 2024-10-11 22:30:16