可被给定的两个数字整除的N位数字的数量

问题描述

我的一个朋友在 google编码竞赛中遇到了这个问题。问题来了。

查找可被X和Y整除的n位数字的数量。 由于答案可能非常大,因此请以10 ^ 9 + 7为模打印答案。

注意::0不被认为是个位数。

输入:N,X,Y。

约束:

  • 1
  • 1

Eg-1
N = 2,X = 5,Y = 7
输出:2(必需的数字是35和70)

Eg-2
N = 1,X = 2,Y = 3
输出:1(6是必需数字)

如果对N的约束较小,则很容易(ans = 10 ^ N / LCM(X,Y)-10 ^(N-1)/ LCM(X,Y))。

但是N最多为1000,因此我无法解决

解决方法

这个问题看起来本来打算更困难,但我会按照您说的方式做:

ans = floor((10 N -1)/ LCM(X,Y))-floor((10 N-1 -1)/ LCM(X ,Y))

诀窍是快速计算条件。

让M = LCM(X,Y),说我们有:

10 a = Mq a + r a ,并且

10 b = Mq b + r b

我们可以轻松地计算出:

10 a + b = M(Mq a q b + r a q b + r b q a + floor(r a r b / M))+( r a r b %M)

使用该公式,我们可以通过平方平方https://en.wikipedia.org/wiki/Exponentiation_by_squaring

以2 log N步来计算10 N / M的商和余数: ,

以下python适用于这个问题,

import math
MOD  = 1000000007

def sub(x,y):
    return (x-y+MOD)%MOD

def mul(x,y):
    return (x*y)%MOD


def power(x,y):
    res = 1
    x%=MOD
    while y!=0:
        if y&1 :
            res = mul(res,x)
        y>>=1
        x = mul(x,x)
        
    return res
        
def mod_inv(n):
    return power(n,MOD-2)

x,y = [int(i) for i in input().split()]

m = math.lcm(x,y)
n = int(input())
a = -1
b = -1
total = 1
for i in range(n-1):
    total = (total * 10)%m
b = total % m
total = (total*10)%m
a = total % m

l = power(10,n-1)
r = power(10,n)

ans = sub( sub(r,l),sub(a,b)   )
ans = mul(ans,mod_inv(m))

print(ans)


这个问题的方法很简单,

让,m = lcm(x,y)

让, 10^n -1 = m*x + a

10^(n-1) -1 = m*y + b

现在从上面的两个方程很明显我们的答案等于 (x - y)%MOD .

所以,

(x-y) = ((10^n - 10^(n-1)) - (a-b)) / m

还有,a = (10^n)%m 和 b = (10^(n-1))%m

使用简单的模算术规则,我们可以在 O(n) 时间内轻松计算出 a 和 b。

对于在公式中执行的减法和除法,我们可以分别使用模减法和除法。

注意:(a/b)%MOD = ( a * (mod_inverse(b,MOD)%MOD )%MOD