codeforce Hello 2018 913G
題目大意:給你一個子串,其在2^k方的十進制表示中出現過(後100位),讓我們求k(k<10^50)
原題鏈接
SOL :
設a長度為n。
可以嘗試構造一個數b,使得a⋅10^m+b成為其後綴。
令 x= a⋅10^m+b,則x=2^k(mod 10^(n+m))
我們發現 2^(n+m)|x,且 not(5|x),
我們先枚舉m ,令 X= a⋅10^m+b,y=a⋅10^m,我們發現y不總是滿足上述性質,那麽我們就對b做出約束:
如果 NOT(2^(N+M)|y) X=y+(2^(N+M)-y%2^(N+M)),
如果 5|X ,我們令 X=y+2^(M+N)
那麽我們便把X構造出來了,那麽我們就只有一個問題了,那就是怎麽求K?
2^K=X(mod 10^(n+m)),同除上2^(N+M),那麽我們得到:
2^(K-M-N)=X/(2^(N+M))(mod 5^(N+M))
這個柿子,我們對其取對數,簡記R=X/(2^(N+M)) 得到:
K-M-N=log2 R(mod 5^(N+M))(這一步牽扯到2個知識點:原根 和 離散對數 )//先掛著dalao的博客吧,以後有空會補的。
那麽我們的問題就是求log2 R
我們知道2 是 5 的原根,那麽2 也是 5^i 的原根。(不失一般性,我們有 p 是姬(奇)質數,q為其原根,那麽q也是 p^l 的原根。l是正整數 )。
由於數量比較大,傳統的baby_step_giant_step算法 過不了,怎麽破?(傳統算法點這裏)
那麽我們有一個比較厲害的柿子:
設dy,i為模pi意義下的log(g)y,存在 j 滿足 di+1=di+j*φ(pi),j∈[0,p)。
#include<bits/stdc++.h> #define LL long long using namespace std; int len(LL x){int a=0; for (;x;a++,x/=10); return a;} LL mul(LL x,LL y,LL mo){ LL anw=0; for (;y>0;y>>=1,x=(x<<1)%mo) if (y&1) (anw+=x)%=mo; return anw; } LL qsm(LL x,LL y,LL mo){ LL anw=1; for (;y>0;y>>=1,x=mul(x,x,mo)) if (y&1) anw=mul(anw,x,mo); return anw; } #define sight(c) (‘0‘<=c&&c<=‘9‘) inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } inline void read(LL &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(LL x){if (x<10) {putchar(‘0‘+x); return;} write(x/10); putchar(‘0‘+x%10);} inline void writeln(LL x){ if (x<0) putchar(‘-‘),x*=-1; write(x); putchar(‘\n‘); } LL n,l,x,T,tp,mo,y,t,k,p5; int main () { read(T); while (T--) { read(k); n=len(k); tp=1; for (int m=0;;m++) { x=k; mo=1ll<<(n+m); if (x%mo) x+=mo-x%mo; if (!(x%5))x+=mo; if ((!(x%mo))&&x%5&&x-k<tp){ y=x>>(n+m); t=0; p5=5; if (y%5==1) t=0; if (y%5==2) t=1; if (y%5==3) t=3; if (y%5==4) t=2; for (int i=1;i<n+m;i++){ while (qsm(2,t,p5*5)!=y%(p5*5)) t+=p5/5*4; p5*=5; } writeln(t+n+m); break; } k*=10,tp*=10; } } }
codeforce Hello 2018 913G