时空限制 2000ms / 128MB
题目描述
给定整数
K
K
K和质数
m
m
m,求最小的正整数
N
N
N,使得
11
⋯
111
⋯
1
(
N
个
1
)
≡
K
(
m
o
d
m
)
11\cdots111⋯1(N个1) \equiv K \pmod m
11⋯111⋯1(N个1)≡K(modm)
说人话:就是 111…1111 mod m =K
输入格式:
第一行两个整数,分别表示KK和mm
输出格式:
一个整数,表示符合条件最小的NN
说明
30%的数据保证
m
≤
1
0
6
m\leq 10^6
m≤106
60%的数据保证
m
≤
5
∗
1
0
7
m\leq 5*10^7
m≤5∗107
100%的数据保证
2
≤
m
≤
1
0
11
,
0
≤
K
<
m
2\leq m\leq 10^{11},0\leq K< m
2≤m≤1011,0≤K<m
题目分析
N
N
N个
1
1
1可以写成
1
0
N
−
1
9
\frac{10^N-1}{9}
910N−1
那么
1
0
N
−
1
9
≡
K
(
m
o
d
  
m
)
⇒
1
0
N
≡
9
K
+
1
(
m
o
d
  
m
)
\frac{10^N-1}{9}\equiv K(\mod m)\Rightarrow\ 10^N\equiv 9K+1(\mod m)
910N−1≡K(modm)⇒ 10N≡9K+1(modm)
裸的BSGS了
然而我脸黑,写龟速乘最后两个点就T
于是无可奈何用了传说中的__int128,就是要手写输入输出
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define lt __int128
using namespace std;
typedef double dd;
lt read()
{
lt x=0,f=1;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
void print(lt x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
map<lt,lt> hh;
lt qpow(lt a,lt k,lt p)
{
lt res=1;
while(k>0){
if(k&1)res=(res*a)%p;
a=(a*a)%p;
k>>=1;
}
return res;
}
lt BSGS(lt a,lt b,lt p)
{
lt t=(lt)sqrt((dd)p)+1; b%=p;
for(lt j=0;j<t;++j)
{
lt tt=b*qpow(a,j,p)%p;
hh[tt]=j;
}
a=qpow(a,t,p);
if(a==0) return b==0?1:-1;
for(lt i=0;i<=t;++i)
{
lt tt=qpow(a,i,p);
lt j=hh.find(tt)==hh.end()?-1:hh[tt];
if(j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}
int main()
{
lt a=10,b=read(),p=read(); b=b*9+1;
print(BSGS(a,b,p));
return 0;
}