洛谷P4884 多少個1?【BSGS】
阿新 • • 發佈:2018-12-11
時空限制 2000ms / 128MB
題目描述
給定整數和質數,求最小的正整數,使得 說人話:就是 111…1111 mod m =K
輸入格式:
第一行兩個整數,分別表示KK和mm
輸出格式:
一個整數,表示符合條件最小的NN
說明
30%的資料保證 60%的資料保證 100%的資料保證
題目分析
個可以寫成 那麼 裸的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;
}