• 【洛谷 P3306】[SDOI2013]随机数生成器 (BSGS)


    题目链接

    怎么这么多随机数生成器

    题意见原题。
    很容易想到(BSGS)算法,但是递推式是(X_{i+1}=(aX_i+b)mod p),这显然不是一个等比数列。
    但是可以用矩阵乘法来求出第(i)项,所以好像可以用(BSGS)套矩阵乘法?但是总要把那个常数项除过来吧,矩阵除法是什么鬼?
    无奈只好放弃去看题解。
    看完之后,哎,我太蒻了。

    [X_{i+1}=(aX_i+b)mod p ]

    [X_{i+1}=a(X_i+frac{b}{a})mod p ]

    [X_{i+1}=(aX_i+frac{ab}{a})mod p ]

    [X_{i+1}=(aX_i+frac{(a-1)b}{a-1})mod p ]

    [X_{i+1}+frac{b}{a-1}=(aX_i+frac{ab}{a-1})mod p ]

    [X_{i+1}+frac{b}{a-1}=a(X_i+frac{b}{a-1})mod p ]

    然后,你发现了什么?
    没错,式子两边都有一个(X+frac{b}{a-1})
    把上面这个式子的左边再乘一个(a)就能得到(X_{i+2}+frac{b}{a-1})
    于是就有

    [X_n+frac{b}{a-1}=a^{n-1}(X_1+frac{b}{a-1})mod p ]

    [frac{X_n+frac{b}{a-1}}{X_1+frac{b}{a-1}}equiv a^{n-1}pmod p ]

    左边的都是已知的,对左边有理数取余,然后就可以(BSGS)了,不会(BSGS)的戳这里
    另外对(a=0,1)或者(X_1=t)要特判一下

    #include <cstdio>
    #include <map>
    #include <cmath>
    #include <cstdlib>
    #define ll long long
    using namespace std;
    int fast_pow(int n, int k, int p){  //n^k%p
        int ans = 1;
        while(k){
          if(k & 1) ans = (long long)ans * n % p;
          n = (long long)n * n % p;
          k >>= 1;
        }
        return ans;
    }
    int BSGS(int a, int b, int p){   //a^x≡b(mod p)
        map <int, int> hash; hash.clear();
        int t = ceil(sqrt(p));
        for(int i = 0; i < t; ++i){
           int val = (long long)b * fast_pow(a, i, p) % p;
           hash[val] = i;
        }
        a = fast_pow(a, t, p);
        if(!a) return !b ? 1 : -1;
        for(int i = 0; i <= t; ++i){
           int j = fast_pow(a, i, p);
           int k = hash.find(j) == hash.end() ? -1 : hash[j];
           if(k >= 0 && (i * t - k) >= 0) return i * t - k;
        }
        return -1;
    }
    void exgcd(int a, int b, int &x, int &y){
        if(!b){
          x = 1; y = 0;
          return;
        }
        exgcd(b, a % b, x, y);
        int z = x; x = y; y = z - (a / b) * y;
    }
    int T;
    int p, a, b, x, t;
    int X, Y;
    int main(){
        scanf("%d", &T);
        while(T--){
          scanf("%d%d%d%d%d", &p, &a, &b, &x, &t);
          if(x == t) { printf("1
    "); continue; }
          if(!a){
            if(t == b) printf("2
    ");
            else printf("-1
    ");
            continue;
          }
          if(a == 1 && !b) { printf("-1
    "); continue; }
          if(a == 1){
            int r = fast_pow(b, p - 2, p);
            printf("%d
    ",(((((long long)t - x) % p + p) % p) * r % p) % p + 1);
            continue;
          }
          int u = fast_pow(a - 1, p - 2, p);
          u = (long long)b * ((u % p + p) % p) %p;
          exgcd((x + u) % p, p, X, Y);
          X = (long long)(t + u) * ((X % p + p) % p) % p;
          int ans = BSGS(a, X, p);
          printf("%d
    ", ~ans ? ans + 1 : ans); 
        }
        return 0;
    }
    
    
  • 相关阅读:
    cassandra安装
    002 spring boot框架,引入mybatis-generator插件,自动生成Mapper和Entity
    033 SSM综合练习09--数据后台管理系统--基于AOP的日志处理
    032 SSM综合练习08--数据后台管理系统--jsp页面显示当前用户名
    031 SSM综合练习07--数据后台管理系统--用户详情查询
    030 SSM综合练习06--数据后台管理系统--SSM权限操作及Spring Security入门
    029 SSM综合练习05--数据后台管理系统--订单分页查询
    027 SSM综合练习03--数据后台管理系统--product-list.jsp和main.jsp页面制作
    Idea 目录结构下有红色波浪线
    virtualbox上,android x86 的分辨率的设置
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9613926.html
Copyright © 2020-2023  润新知