編程之美2.8——找符合條件的整數

任意給定一個正整數N,求一個最小的正整數M(M>1),使得N*M的十進制表示形式裏只含有1和0.算法

如N=3,M=39,N*M=111。數組

【思路】spa

這麼難的思路打死我也想不到.@_@|||||..code

將題目轉換爲,求一個數X,使得X%N=0且X的十進制表示只含有1和0.blog

維護一個「餘數數組」,對於從0到N-1的每個餘數,都有相應的最小X;class

高位能夠利用低位的餘數歸隊,X=10^k+Y(10的k次方,^表示次方)X%N=(10^k%N+Y%N).擴展

直到找到餘數爲0對應的最小值。date

【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;
}

【評價】di

維護兩個數組,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.

最後要轉化成十進制表示。

相關文章
相關標籤/搜索