如何找到可以被7整除的数字计数?

时间:2019-10-05 10:07:42

标签: algorithm dynamic-programming

给定一个整数N,如何有效地找到以下范围内被7整除的数(它们的倒数也应被7整除):

  • [0, 10^N - 1]

示例:

对于N=2,请回答:

  • 4 {0, 7, 70, 77}

[从0到99的所有数字都可以被7整除(也可以将它们的反数整除)]

我的方法,简单的蛮力:

  • 将计数初始化为零
  • i=0到结束运行循环
  • 如果a(i) % 7 == 0 && reverse(a(i)) % 7 == 0,那么我们增加计数

注意:

    例如,
  • reverse(123) = 321reverse(1200) = 21

3 个答案:

答案 0 :(得分:3)

让我们看看将数字d添加到前缀abc时mod 7会发生什么。

10 * abc + d =>
  (10 mod 7 * abc mod 7) mod 7 + d mod 7

reversed number:

abc + d * 10^(length(prefix) =>
  abc mod 7 + (d mod 7 * 10^3 mod 7) mod 7

请注意,对于每个这样的余数,我们只需要abc mod 7的前缀数,而不是实际的前缀。

答案 1 :(得分:3)

COUNTS(n,f,r)为n位数字的数量,以使 n%7 = f REVERSE(n)% 7 = r

很容易计算 n = 1 的计数:

COUNTS(1,f,r)= 0 (当 f!= r 时),因为1位数与它的倒数相同。

COUNTS(1,x,x)= 1 ,当 x> = 3 ,并且

x <3 时,

COUNTS(1,x,x)= 2 ,因为7%3 = 0、8%3 = 1和9%3 = 2

其他长度的计数可以通过计算将0到9的每个数字加到以前计数所表示的数字上时会发生的情况来得出。

最后, COUNTS(N,0,0)是您要寻找的答案。

例如,在python中,它看起来像这样:

def getModCounts(len):
    counts=[[0]*7 for i in range(0,7)]
    if len<1:
        return counts
    if len<2:
        counts[0][0] = counts[1][1] = counts[2][2] = 2
        counts[3][3] = counts[4][4] = counts[5][5] = counts[6][6] = 1
        return counts
    prevCounts = getModCounts(len-1)
    for f in range(0,7):
        for r in range(0,7):
            c = prevCounts[f][r]
            rplace=(10**(len-1))%7
            for newdigit in range(0,10):
                newf=(f*10 + newdigit)%7
                newr=(r + newdigit*rplace)%7
                counts[newf][newr]+=c
    return counts

def numFwdAndRevDivisible(len):
    return getModCounts(len)[0][0]

#TEST
for i in range(0,20):
    print("{0} -> {1}".format(i, numFwdAndRevDivisible(i)))

查看它是否提供您期望的答案。如果没有,也许我需要修复一个错误:

0 -> 0
1 -> 2
2 -> 4
3 -> 22
4 -> 206
5 -> 2113
6 -> 20728
7 -> 205438
8 -> 2043640
9 -> 20411101
10 -> 204084732
11 -> 2040990205
12 -> 20408959192
13 -> 204085028987
14 -> 2040823461232
15 -> 20408170697950
16 -> 204081640379568
17 -> 2040816769367351
18 -> 20408165293673530
19 -> 204081641308734748

当计数到N是合理的时候,这是一个很好的答案- way 比蛮力强,计数高达10 ^ N。

对于很长的长度(例如N = 10 ^ 18)(可能会要求您输入count mod 1000000007之类的东西),会有一个下一层的答案。

请注意,长度 n 的计数与长度 n + 1 的计数之间存在线性关系,并且该关系可以由49x49矩阵表示。您可以通过对O(log N)矩阵乘法求平方,然后使用幂运算将矩阵求幂到第 N 次,然后乘以一位数即可得到长度N个计数。

答案 2 :(得分:1)

对于任何数字,都有使用数字dp技术的递归解决方案。

long long call(int pos , int Mod ,int revMod){
    if(pos == len ){
        if(!Mod && !revMod)return 1;
        return 0;
    }
    if(dp[pos][Mod][revMod] != -1 )return dp[pos][Mod][revMod] ;

    long long res =0;
    for(int i= 0; i<= 9; i++ ){
        int revValue =(base[pos]*i + revMod)%7;
        int curValue = (Mod*10 + i)%7;
        res += call(pos+1, curValue,revValue) ;
    }

    return dp[pos][Mod][revMod] = res ;
}