zoukankan      html  css  js  c++  java
  • 编程之美2.8——找符合条件的整数

    任意给定一个正整数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.

    最后要转化成十进制表示。

  • 相关阅读:
    父子进程 signal 出现 Interrupted system call 问题
    一个测试文章
    《淘宝客户端 for Android》项目实战 html webkit android css3
    Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构
    coreseek 出现段错误和Unigram dictionary load Error 新情况(Gentoo)
    一个 PAM dbus 例子
    漫画统计学 T分数
    解决 paramiko 安装问题 Unable to find vcvarsall.bat
    20141202
    js
  • 原文地址:https://www.cnblogs.com/ketchups-notes/p/4514797.html
Copyright © 2011-2022 走看看