51Nod 1359 循环探求

51Nod 1359 循环探求


题意

输入n和k,求最小 x (x > 1)使得 n^x % (10^k) == n % (10^k)
n(1 <= n < 10^600)和k(1 <= k <= 600)

做法

由于x>1, 对原式变形有
n * n^x % (10^k) == n % (10^k)
则答案为x+1
另外,还有
n % (10^k) = n * n^x % (10^k)
用上式进行等量代换
n * n^x % (10^k) = (n * n^x) * n^x % (10^k) = n * (nx)2 % (10^k)
= ...
= n * (nx)t % (10^k)
且 t > 1

先考虑mod[1] = 10,找到最小的x1使得
n * (n^x1) % mod1 == n % mod1
由上可知
n * (nx1)t % mod1 == n % mod1
及给x1乘t不会影响mod1下的情况,因此令n1 = n^x1,mod2 = 100, 有
n * n1^t % mod2 == n % mod2
找到一个最小的t满足上式,则答案是x1*t+1

进一步枚举k,可得到一组等式
n * n(k-1)^xk % modk == n modk
因此,可以递推求解。

接下来的问题是如何找到n * (n^x1) % mod1 == n % mod1中的x1
可以注意到,mod = 10^(k-1)时,的后k-1位两边一定相等,而mod = 10^k时,数位仅仅多了一位,因此这一位数只有10种可能,因此枚举连续11个t后一定可以进入循环之中,并枚举完所有的解,因此每次把t从1枚举到20

由于数据的范围,这里使用python实现,需要注意,中间变量需要模10^k,来保证复杂度,否则很容易超时

N,K = map(int,input().split(' '))
M = 10**K
N %= M
n = N
mod = 10
ans = 1
for k in range(1,K+1):
    flag = 0
    for xk in range(1,21):
        tmp = (n**xk) % M
        if (N * tmp) % mod == N % mod:
            flag = 1
            ans *= xk
            n = tmp
            mod = mod * 10
            break
    if flag == 0:
        ans = 0
        break

print(ans+1)
原文地址:https://www.cnblogs.com/RRRR-wys/p/13688121.html