• Bzoj3122:多项式BSGS


    根据鸽笼原理,在p次后一定循环,一眼BSGS。
    发现他给的函数是个一次函数,一次函数有什么性质呢?f(f(x))还是一次函数,这样就能做了。
    首先我们暴力预处理出f(f(f(x)))......sqrt(p)层的f(x)。
    然后预处理出前sqrt(p)迭代后的值。
    我们可以用exgcd求出如果让f(x)=t,我们需要的x值。
    然后我们枚举用多少层迭代sqrt(p)后的f(x)即可。
    注意特判一下a==0的情况,因为exgcd无法处理有0的参数。
    为什么跑得如此之慢?可能我需要一个unordered_map,然而C++11不能用......

    代码:

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<map>
     4 typedef long long int lli;
     5 using namespace std;
     6 
     7 lli mod;
     8 
     9 struct Poly {
    10     lli k,b;
    11     inline Poly inter(const Poly &t) {
    12         return (Poly){t.k*k%mod,(t.b*k%mod+b)%mod};
    13     }
    14     inline lli ite(const lli &x) {
    15         return ( k * x % mod + b ) % mod;
    16     }
    17 }now,trans,sqr;
    18 
    19 inline lli exgcd(lli a,lli b,lli &x,lli &y) {
    20     if( !b ) {
    21         x = 1 , y = 0;
    22         return a;
    23     }
    24     lli ret = exgcd(b,a%b,y,x);
    25     y -= ( a / b ) * x;
    26     return ret;
    27 }
    28 
    29 inline lli getx(const Poly &p,const lli &t) {
    30     lli x,y,rit;
    31     exgcd(p.k,mod,x,y);
    32     rit = ( t - p.b + mod ) % mod , x = ( x % mod + mod ) % mod;
    33     return x * rit % mod;
    34 }
    35 
    36 inline lli bsgs(lli a,lli b,lli x,lli t) {
    37     if( !a && !b ) return x == t ? 1 : -1;
    38     map<lli,lli> mp;
    39     int sq = ( (double) sqrt(mod) + 0.5 ) + 1;
    40     sqr = now = (Poly){1,0} , trans = (Poly){a,b};
    41     for(int i=1;i<=sq;i++) {
    42         if( mp.find(x) == mp.end() ) mp[x] = i;
    43         x = trans.ite(x);
    44     }
    45     for(int i=1;i<=sq;i++) sqr = trans.inter(sqr);
    46     for(int i=0;i<=sq;i++) {
    47         lli tx = getx(now,t);
    48         if( mp.find(tx) != mp.end() ) return mp[tx] + i * sq;
    49         now = sqr.inter(now);
    50     }
    51     return -1;
    52 }
    53 
    54 int main() {
    55     static int T;
    56     static lli a,b,x,t;
    57     scanf("%d",&T);
    58     while(T--) {
    59         scanf("%lld%lld%lld%lld%lld",&mod,&a,&b,&x,&t);
    60         printf("%lld
    ",bsgs(a,b,x,t));
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    前端资源网址
    IDEA激活工具
    新建jsp项目
    jsp笔记
    iOS的SVN
    iOS学习网站
    测试接口工具
    MVP模式
    关于RxJava防抖操作(转)
    注释模板
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8663021.html
Copyright © 2020-2023  润新知