• bzoj 3122 随机数生成器


    Description

    Input

    输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。  
     
    接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据。保证X1和t都是合法的页码。 

    注意:P一定为质数

    Output

    共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。 

    Sample Input

    3
    7 1 1 3 3
    7 2 2 2 0
    7 2 2 2 1


    Sample Output


    1
    3
    -1

    HINT

    0<=a<=P-1,0<=b<=P-1,2<=P<=10^9

    题目大意

      给定一个序列$X$的首项$x_{1}$,序列$X$满足递推关系$x_{n + 1} = (acdot x_{n} + b)mod p$,其中这里的$mod$表示求余数。问序列中哪个数第一次为$t$,或者输出无解。

      显然递推关系对方程不是特别友好,所以考虑求序列的通项。

      由于这里用特征根的方法来求会很繁琐,所以直接展开:

    $x_{n} = left ( acdot x_{n - 1} + b ight ) mod p$

    $x_{n} = left ( a^{2}cdot x_{n - 2} + ab + b ight ) mod p$

    $x_{n} = left ( a^{n - 1}cdot x_{1} + a^{n-2}b + cdots + ab + b ight ) mod p$

      用等比数列求和公式得到:

    $x_{n} = left [ a^{n - 1}cdot x_{1} + frac{left (a^{n - 1} - 1  ight )b}{a - 1} ight ] mod p (a eq 1)$

    $x_{n} = frac{a^{n - 1}cdot x_{1}left ( a - 1 ight ) + left (a^{n - 1} - 1  ight )b}{a - 1} mod p (a eq 1)$

    $x_{n} = frac{a^{n - 1}cdotleft [ x_{1}left ( a - 1 ight ) + b  ight ]  - b}{a - 1} mod p (a eq 1)$

      然后再移项:

    $a^{n - 1}cdotleft [ x_{1}left ( a - 1 ight ) + b  ight ] equiv left ( a - 1 ight )x_{n} + b pmod{p} (a eq 1)$

      BSGS解方程即可。

      继续考虑$a = 1$的情况,此时有:

    $x_{n} equiv x_{1} + left ( n - 1 ight )b pmod{p} left ( a = 1 ight )$

      写成不定方程的形式:

    $ncdot b + kcdot p = x_{n}+ b - x_{1} left ( a = 1 ight )$

      直接扩欧算答案。

      注意一个细节,扩欧如果算出答案模$p$为0,那么应该输出$p$,因为这里求的是最小正余数。

      似乎$a = 0$的时候,要加点处理,不然扔进去的东西变成负数,BSGS也会出事情。干脆直接特判。

    Code

      1 /**
      2  * bzoj
      3  * Problem#3122
      4  * Accepted
      5  * Time: 268ms
      6  * Memory: 2028k
      7  */
      8 #include <iostream>
      9 #include <cstring>
     10 #include <cstdio>
     11 #include <cmath>
     12 using namespace std;
     13 typedef bool boolean;
     14 
     15 typedef class HashMap {
     16     private:
     17         static const int M = 46666; 
     18     public:
     19         int ce;
     20         int h[M], key[M], val[M], next[M];
     21         
     22         HashMap() {    }
     23         
     24         void insert(int k, int v) {
     25             int ha = k % M;
     26             for (int i = h[ha]; ~i; i = next[i])
     27                 if (key[i] == k) {
     28                     val[i] = v;
     29                     return;
     30                 }
     31             ++ce, key[ce] = k, val[ce] = v, next[ce] = h[ha], h[ha] = ce;
     32         }
     33         
     34         int operator [] (int k) {
     35             int ha = k % M;
     36             for (int i = h[ha]; ~i; i = next[i])
     37                 if (key[i] == k)
     38                     return val[i];
     39             return -1;
     40         }
     41         
     42         void clear() {
     43             ce = -1;
     44             memset(h, -1, sizeof(h));
     45         }
     46 }HashMap; 
     47 
     48 
     49 int qpow(int a, int pos, int m) {
     50     int pa = a, rt = 1;
     51     for ( ; pos; pos >>= 1, pa = pa * 1ll * pa % m)
     52         if (pos & 1)
     53             rt = rt * 1ll * pa % m;
     54     return rt;
     55 }
     56 
     57 int gcd (int a, int b) {
     58     return (b) ? (gcd(b, a % b)) : (a);
     59 }
     60 
     61 void exgcd(int a, int b, int& d, int &x, int &y) {
     62     if (!b)
     63         d = a, x = 1, y = 0;
     64     else {
     65         exgcd(b, a % b, d, y, x);
     66         y -= (a / b) * x;
     67     }
     68 }
     69 
     70 int inv(int a, int n) {
     71     int d, x, y;
     72     exgcd(a, n, d, x, y);
     73     return (x < 0) ? (x + n) : (x);
     74 }
     75 
     76 int T;
     77 int p, a, b, x1, t;
     78 
     79 inline void init() {
     80     scanf("%d%d%d%d%d", &p, &a, &b, &x1, &t);
     81 }
     82 
     83 HashMap mp;
     84 inline int ind(int x, int a, int p, int pro) {
     85     mp.clear();
     86     int cs = sqrt(p - 1 + 0.5);
     87     int ainv = inv(x, p), iap = a * 1ll * qpow(ainv, cs - 1, p) % p;
     88     for (int i = cs - 1; ~i; i--, iap = iap * 1ll * x % p)
     89         mp.insert(iap, i);
     90     int cp = qpow(x, cs, p), pw = pro;
     91     for (int i = 0; i < p; i += cs, pw = pw * 1ll * cp % p)
     92         if (~mp[pw])
     93             return mp[pw] + i;
     94     return -2;
     95 }
     96 
     97 inline int solve1() {
     98     if (!b)    return (t == x1) ? (1) : (-1);
     99     int d, x, y, go = t + b - x1;
    100     exgcd(b, p, d, x, y);
    101     x = x * 1ll * go % p;
    102     return (x <= 0) ? (x + p) : (x);
    103 }
    104 
    105 inline void solve() {
    106     if (a == 0)
    107         printf("%d
    ", (t == x1) ? (1) : ((b == t) ? (2) : (-1)));
    108     else if (a == 1)
    109         printf("%d
    ", solve1());
    110     else
    111         printf("%d
    ", ind(a, ((a - 1) * 1ll * t + b) % p, p, (x1 * 1ll * (a - 1) + b) % p) + 1);
    112 }
    113 
    114 int main() {
    115     scanf("%d", &T);
    116     while (T--) {
    117         init();
    118         solve();
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    根据navigator.userAgent返回值识别 浏览器
    HTML兼容问题及解决办法
    css 浏览兼容问题及解决办法 (2)
    css 浏览兼容问题及解决办法 (1)
    js 浏览器兼容问题及解决办法
    cookie 笔记
    HTML5基础2
    HTML5基础1
    摩天轮
    造个惊喜盒( ๑ŏ ﹏ ŏ๑ )
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8480816.html
Copyright © 2020-2023  润新知