【题目描述】
给定整数K和质数m,求最小的正整数N,使得 11111⋯1(N个1) ≡K(modm)
说人话:就是 111…1111 mod m =K
【输入格式】
第一行两个整数,分别表示K和m
【输出格式】
一个整数,表示符合条件最小的N
S a m p l e I n p u t Sample~~Input Sample Input
9 17
S a m p l e O u t p u t Sample~~Output Sample Output
3
【题意分析】
111
⋯
1
(
x
个
1
)
=
1
0
x
−
1
9
111\cdots1(x个1)=\frac{10^x-1}{9}
111⋯1(x个1)=910x−1
所以
111
⋯
1
(
x
个
1
)
≡
k
(
m
o
d
p
)
111\cdots1(x个1)\equiv k(mod~p)
111⋯1(x个1)≡k(mod p)
就是求
1 0 x ≡ 9 k + 1 ( m o d p ) 10^x\equiv9k+1(mod~p) 10x≡9k+1(mod p)
保证p是质数,裸的BSGS即可
但是sb出题人卡long long,再用__int128就行了
我用了神奇的乘法分配律 O ( 1 ) O(1) O(1)龟速乘,我也不知道是什么原理。。。
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
__int128 b, p;
inline __int128 read () {
register __int128 s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
return s * w;
}
void write (__int128 x) {
if (x < 0) putchar ('-'), x = -x;
if (x > 9) write (x / 10);
putchar (x % 10 + '0');
}
__int128 pow (__int128 a, __int128 b, __int128 qy) {
if (! b) return 1; if (b == 1) return a;
__int128 base = 1;
while (b) {
if (b & 1) base = base * a % qy;
a = a * a % qy, b >>= 1;
}
return base;
}
__int128 mul (__int128 a, __int128 b, __int128 P){
__int128 L = a * (b >> ((__int128)25)) % P * (((__int128)1) << 25) % P;
__int128 R = a * (b & (((__int128)1) << 25) - 1) % P;
return (L + R) % P;
}
__int128 BSGS (__int128 a, __int128 b, __int128 qy) {
map <__int128, __int128> hash;
__int128 lim = (__int128) ceil (sqrt ((double)qy)), base = b % qy;
for (register __int128 i = 1; i <= lim; i++) hash[mul (b, pow (a, i, qy), qy)] = i;
base = pow (a, lim, qy);
__int128 o = 1;
for (register __int128 i = 1; i <= lim; i++) {
o = o * base % qy;
if (hash[o]) return ((i * lim - hash[o]) % qy + qy) % qy;
}
return -1;
}
signed main () {
b = read (), p = read ();
b = (b * 9 + 1) % p;
write (BSGS (10, b, p));
return 0;
}