标签:
任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0.
如N=3,M=39,N*M=111。
【思路】
这么难的思路打死我也想不到.@_@|||||..
将题目转换为,求一个数X,使得X%N=0且X的十进制表示只含有1和0.
维护一个“余数数组”,对于从0到N-1的每一个余数,都有相应的最小X;
高位可以利用低位的余数归队,X=10^k+Y(10的k次方,^表示次方)X%N=(10^k%N+Y%N).
直到找到余数为0对应的最小值。
【other code】——via xiaodongrush
int find_m(int n) { if(n==1) return 1; int factor=10; int *A=new int[n];//A[i]保存余数为i时对应的最小数 int *B=new int[n];//B[i]保存余数为i的当前数 bool not_find=true; memset(A, -1, n*sizeof(int)); A[1]=1; while(not_find){ memset(B, -1, n*sizeof(int)); int x=factor%n;//余数 if(A[x]==-1){ B[x]=factor; if(x==0) break; } for(int i=1; i<n; i++){ if(A[i]==-1) continue; int new_x=(x+i)%n; if(A[new_x]==-1&&B[new_x]==-1){ B[new_x]=factor+A[i]; if(new_x==0){ not_find=false; break; } } } factor*=10; for(int i=0; i<n; i++){ if(A[i]==-1&&B[i]!=-1) A[i]=B[i]; } } int result=B[0]; delete [] A; delete [] B; return result; }
【评价】
维护两个数组,A保存余数对应的最小值,B保存当前值,每当有新余数时便扩展。按照书上的算法来的,十分严密,对于我来说已经很perfect了。
【书上的伪代码】
int find_m1(int n) { int Noupdate=0; int i,j; vector<vector<int> > BigInt(n); for(int i=0; i<n; i++) BigInt[i].clear(); BigInt[1].push_back(0); for(i=1, j=10%n; ; i++, j=(j*10)%n){ bool flag=false;//判断是否更新 if(BigInt[j].size()==0){ flag=true; BigInt[j].clear(); BigInt[j].push_back(i); } for(int k=1; k<n; k++){ if((BigInt[k].size()>0)&& (i>BigInt[k][BigInt[k].size()-1])&& (BigInt[(j+k)%n].size()==0)){ flag=true; BigInt[(j+k)%n]=BigInt[k]; BigInt[(j+k)%n].push_back(i); } } if(flag==false) Noupdate++; else Noupdate=0; if(Noupdate==n||BigInt[0].size()>0) break; } if(BigInt[0].size()==0) return -1; else{ int result=0; int factor=1; for(int k=0; k<BigInt[0].size(); k++){ for(int r=0; r<BigInt[0][k]; r++) factor*=10; result+=factor; factor=1; } return result; } }
【总结】
伪代码中10^k表示的是异或运算。用一个vector<vector<int> >来保存余数信息。
BigInt[i]是余数i对应最小数的有1的位置,比如对于n=3,BigInt[0] (0,1,2)代表第0,1,2位都有1,即111.
最后要转化成十进制表示。
标签:
原文地址:http://www.cnblogs.com/ketchups-notes/p/4514797.html