1. 程式人生 > >洛谷P4884 多少個1?【BSGS】

洛谷P4884 多少個1?【BSGS】

時空限制 2000ms / 128MB

題目描述

給定整數KK和質數mm,求最小的正整數NN,使得 111111N1K(modm)11\cdots111⋯1(N個1) \equiv K \pmod m 說人話:就是 111…1111 mod m =K

輸入格式:

第一行兩個整數,分別表示KK和mm

輸出格式:

一個整數,表示符合條件最小的NN

說明

30%的資料保證m106m\leq 10^6 60%的資料保證m5107m\leq 5*10^7 100%的資料保證2m1011,0K<m2\leq m\leq 10^{11},0\leq K< m

題目分析

NN11可以寫成10N19\frac{10^N-1}{9} 那麼10N19K(mod  m)10N9K+1(mod  m)\frac{10^N-1}{9}\equiv K(\mod m)\Rightarrow\ 10^N\equiv 9K+1(\mod m) 裸的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; }