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.

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

  • 相关阅读:
    解决Ubuntu下gedit中文乱码
    Linux下安装Matlab软件
    3.5mm耳机/麦克接头
    IIS无法加载PHP.ini
    修改mysql用户密码
    dhtmlxgrid使用基础
    远程桌面“终端服务器超出了最大允许连接数”的解决
    MATLAB中格式化M文件注释
    MATLAB中使用Cell对M文件分节
    MATLAB下一些常用易忘命令
  • 原文地址:https://www.cnblogs.com/ketchups-notes/p/4514797.html
Copyright © 2011-2022 走看看