问题描述
我的一个朋友在 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