• 第2章 数字之魅——数字中的技巧2.8


    2.8找符合条件的整数

    问题描述:给定一个正整数N,求一个最小正整数M(M>1),使得N*M的十进制表示形式里只含有1和0.

    最直接了当的方法。当然就是对M无限穷举下去。

    书上提供了一个逆向考虑的方法。

    其实重点是思想。

    我们可以穷举N*M。即由1和0构成的串。

    相比穷举M而言。N*M的数量级小得多了多!。

    而且我们判断合法的时候只要判断构造出来的串是否整除N.即可。

    相似的。曾经遇到过一个这样的问题。

    输入数据N,M。其中0<N<M<1e9。打印出[N,M]中的回文素数。

    有常识的话。可以知道1e9素数数量有500W。我们并不容易能够先筛出素数表。

    即使空间允许。时间也不允许。

    而这时。我们可以考虑去构造回文串。回文串的数量比素数的数量小得多。然后我们再去判断构造出来的回文数是否是素数。

    对于这个问题。已经包含了“避多就少”的转化思想。

    于是我们同样地可以思考这样的一个问题。已知N. 求M

    使得N*M为一个回文素数。

    这个问题就不加以分析了。

    回归正题。

    然而我们并不满足于穷举0 1串的复杂度(实际上其复杂度还是相当高的)。

    这里利用和式的同余定理:

    a mod p = m1 , b mod p = m2  -> (a+b) mod p = (a mod p + b mod p) mod p = (m1+m2) mod p 

    针对整除问题的优化。

    根据长度对我们构造出来的串进行划分。

    1     10,11   100,101,110,111 ...

    容易发现一个问题。

    长度长的串除了原串 (1 10 100...)以外。都是由原串和长度小的串构成的。

    比如 111 是由 100 + 11.

           110 是由 100 + 10.

           101 是由 100 + 1.

    由此。我们可以利用动态规划的思想。保留处理出的结果为后续使用。(这里的结果其实就是余数)。

    同时你会发现一个问题。

    假如N = 3.

    1  mod 3 = 1. 10 mod 3 = 1.即1 和 10 对于3 来说是等价的。

    那么同理。  101 110 对于3来说也是等价的。

    我们是否可以避免101 110这样的运算的呢?

    答案当然是可以的。

    我们可以只保留余数信息。同时可以在这个余数信息里存最小的串元素。

    比如 BigInt[1] = 1.

    这样的话。我们就不会重复计算同余数的数了。

    套用编程之美上面的伪码。

    <代码>

    代码上令BigInt[]  为向量数组。方便操作。

    同时放入i 是为了防止更新在当前长度新产生的余数集。

    就比如:N = 3 的例子

    1%3 = 1 有余数集1。

    10%3 = 1 。余数集1已经存在。那么更新1+1 = 2 的余数集。

    (在这之前都没问题,看下面。)

    100%3 = 1 。余数集1已经存在。那么我们对余数集1 2 进行更新操作。 1+1=2 已经存在。 1+2 = 3 更新出3的集

    (这是正常的操作)。

    假如没有放入i。

    就会变成

    100%3 = 1。 余数1存在略过。1+1 = 2 存在略过。1+3 = 3 更新出3。之后又 1+3 = 4 更新出4 。 1+4 = 5 更新出 5 。

  • 相关阅读:
    xp系统优化
    项目开发文档格式13种 (转载)
    java 操作 ORACLE
    orclae temp table
    把EXCEL上传并BINDING到GRIDVIEW中
    从excel读数据写入数据库代码
    GMDatePicker控件的使用
    代码汇总
    dwr运行时出现Servlet.init() for servlet dwrinvoker threw exception的解决方法
    CVSNT安装
  • 原文地址:https://www.cnblogs.com/Milkor/p/4506805.html
Copyright © 2020-2023  润新知