algorithm - 如何找到除以给定数字的只有 0 和 1 的最小数字?

标签 algorithm math division

每个正整数除以某个数字,该数字的表示形式(以 10 为底)仅包含零和一。

可以证明:

考虑数字 1、11、111、1111 等直到 111...1,其中 最后一个数字有 n+1 位。称这些数字为 m1、m2、...、mn+1。每个都有一个 除以 n 的余数,并且其中两个余数必须相同。 因为它们有 n+1 个,但余数只能取 n 个值。 这是著名且有用的“鸽巢原理”的应用;

假设余数相同的两个数是mi和mj ,我 < j。现在从较大的中减去较小的。结果数 mi−mj 由 j - i 个 1 后跟 i 个零组成,必须是 n 的倍数。

但是如何找到最小的答案呢?并且高效?

最佳答案

这道题等于用10i mod n(对于每个i,最多可以用一次)得到n的和m。这就像背包问题或子集和问题。这样,动态规划将完成任务。

在动态规划中,复杂度是O(k*n)。 k 是答案中的位数。对于 n<105,此代码完美运行。

代码:

#include <stdio.h>
#define NUM 2000

int main(int argc, char* argv[])
{
    signed long pow[NUM],val[NUM],x,num,ten;
    int i,j,count;
    for(num=2; num<NUM; num++)
    {
        for(i=0; i<NUM; pow[i++]=0);
        count=0;
        for(ten=1,x=1; x<NUM; x++)
        {
            val[x]=ten;

            for(j=0; j<NUM; j++)if(pow[j]&&!pow[(j+ten)%num]&&pow[j]!=x)pow[(j+ten)%num]=x;
            if(!pow[ten])pow[ten]=x;
            ten=(10*ten)%num;
            if(pow[0])break;
        }

        x=num;
        printf("%ld\tdivides\t",x=num);
        if(pow[0])
        {
            while(x)
            {
                while(--count>pow[x%num]-1)printf("0");
                count=pow[x%num]-1;
                printf("1");
                x=(num+x-val[pow[x%num]])%num;
            }
            while(count-->0)printf("0");
        }
        printf("\n");
    }
}

附言: OEIS 中的此序列.

关于algorithm - 如何找到除以给定数字的只有 0 和 1 的最小数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28436888/

相关文章:

assembly - 6502 的快速有符号 16 位除以 7

c++ - C++ 中的快速排序实现(失败测试)

algorithm - 这是什么类似的背包?组建最佳团队

language-agnostic - 是否有将四元数旋转转换为欧拉角旋转的算法?

python - 从 RANSAC 回归中提取系数

algorithm - 如何找到除以给定数字的只有 0 和 1 的最小数字?

algorithm - 约翰逊算法 - h 函数

algorithm - 给定一个数字大于另一个数字的 2 个数字的可能结果数

java - 度数计算不正确,哪里出错了?

java - 数字与分数相乘