2018 Arab Collegiate Programming Contest (ACPC 2018) H - Hawawshi Decryption 数学 + BSGS

H - Hawawshi Decryption

对于一个给定的生成数列

R[ 0 ] 已知, (R[ i - 1 ] * a + b) % p = R[ i ] (p 是 质数), 求最小的 x 使得 R[ x ] = t

我们假设存在这样一个数列 S[ i ] = R[ i ] - v, 并且S[ i - 1] * a = S[ i ], 那么将S[ i ] = R[ i ] - v带入可得

v = b / (1-a) 那么我们能得到 R[ i ] = (R[ 0 ] - v) * a ^ n + v, 然后就是解一个高次剩余方程,

注意 a == 1 和 R[ 0 ] == v的情况需要特殊考虑。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 1e4 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

int n, x, L, R, a, b, p, T, y;

struct hashTable {
    int head[N+5], tot;
    struct node {
        int val, id, nx;
    } a[N+5];
    void init() {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void Insert(int val, int id) {
        int p = val % N;
        a[tot].val = val;
        a[tot].id = id;
        a[tot].nx = head[p];
        head[p] = tot++;
    }
    int Find(int val) {
        int p = val % N;
        for(int i = head[p]; ~i; i = a[i].nx)
            if(a[i].val == val) return a[i].id;
        return -1;
    }
} mp;

int fastPow(int a, int b) {
    int ans = 1;
    while(b) {
        if(b & 1) ans = 1ll*ans*a%p;
        a = 1ll*a*a%p; b >>= 1;
    }
    return ans;
}

int BSGS(int a,int b,int p) {
    if(b == 1) return 0;
    if(a == b) return 1;
    if(!b) return !a ? 1 : -1;
    mp.init();
    int m = ceil(sqrt(p)), x = 1, y, z;
    for(int i = 1; i <= m; i++) {
        x = 1ll * x * a % p;
        if(mp.Find(x) == -1) mp.Insert(x, i);
    }
    x = 1, y = fastPow(a, p-m-1);
    for(int i = 0; i < m; ++i) {
        z = mp.Find(1ll*x*b%p);
        if(~z) return i * m + z;
        x = 1ll * x * y % p;
    }
    return -1;
}

int main() {
//    freopen("hawawshi.in", "r", stdin);
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d%d%d%d%d", &n, &x, &L, &R, &a, &b, &p);
        int q = 0, r = R-L+1;
        if(a == 1) {
            for(int R0 = L; R0 <= R; R0++) {
                int pos = 1ll*(x-R0+p)%p*fastPow(b, p-2)%p;
                if(pos < n) q++;
            }
        } else {
            int v = 1ll * b * fastPow(1-a+p, p-2) % p;
            for(int R0 = L; R0 <= R; R0++) {
                if(R0 == v) {
                    if(R0 == x) q++;
                } else {
                    int pos = BSGS(a, 1ll*(x-v+p)%p*fastPow((R0-v+p)%p, p-2)%p, p);
                    if(~pos && pos < n) q++;
                }
            }
        }
        int gcd = __gcd(q, r);
        printf("%d/%d\n", q/gcd, r/gcd);
    }
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10263739.html
今日推荐