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

Number of N-digit numbers that are divisible by given two numbers

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

求出能同时被 X 和 Y 整除的 N 位数字的个数。 由于答案可能非常大,打印答案模 10^9 + 7.

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

输入: N、X、Y。

约束条件:

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

例如-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((10N-1)/LCM(X,Y)) - floor((10N-1-1)/LCM(X,Y))

诀窍是快速计算项。

令 M = LCM(X,Y),并假设我们有:

10a = Mqa + ra, and

10b = Mqb + rb

我们可以很容易地计算出:

10a+b = M(Mqaqb + raqb + rbqa + 地板(r arb/M)) + (rarb%M)

使用该公式,我们可以使用平方取幂计算 10N/M 的商和余数,仅需 2 log N 步:https://en.wikipedia.org/wiki/Exponentiation_by_squaring

以下 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