码迷,mamicode.com
首页 > 其他好文 > 详细

codeforce Hello 2018 913G

时间:2018-01-15 22:45:34      阅读:320      评论:0      收藏:0      [点我收藏+]

标签:detail   str   这一   ret   int   ant   getc   知识点   .com   

题目大意:给你一个子串,其在2^k方的十进制表示中出现过(后100位),让我们求k(k<10^50)

原题链接

SOL :

a长度为n。 
可以尝试构造一个数b,使得a10^m+b成为其后缀。

令  x= a10^m+b,则x=2^k(mod 10^(n+m))

我们发现 2^(n+m)|x,且 not(5|x),

我们先枚举m ,令  X= a10^m+b,y=a10^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

标签:detail   str   这一   ret   int   ant   getc   知识点   .com   

原文地址:https://www.cnblogs.com/rrsb/p/8289591.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!