bzoj-1467 clever Y / JDFZ-2940 EXBSGS

题意:

求解方程A^x=B (mod C)在[0,C)中的最小解;

C<=10^9;

题解:

此题C并不是质数,所以要用一种叫做EXBSGS的东西来解;

考虑BSGS的适用条件,主要是在于A^k也就是A不一定对于C有逆元;

那么约下去一些怎么样?

令d=gcd(A,C),那么一定有 d|B或者x=0,B=1;

x=0的情况比较特殊,直接特判即可;

那么若没有d|B则无解;

而如果同时除一个B之后,方程即为A/d*A^(x-1)=B/d (mod C/d);

多次执行该操作,直到gcd(A,C/d1*d2*d3*...*dk)=1为止;

设P=d1*d2*d3*...*dk这一大坨;

此时方程为(A^k/P)*A^(x-k)=B/P (mod C/P);

这个方程是支持BSGS的!直接套用即可;

然后解决了?

等等,x-k为负怎么办?

...暴力啊!因为C每次都除一个数,所以最多除不过logC次;

枚举到logC判断是否出解就可以了,也顺便把之前x=0的特判统一了;

时间复杂度O(logC+√C/P);

代码:

//代码是JDFZ的代码,多了关于C==1的特判;

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 140142
using namespace std;
typedef long long ll;
struct Hash_Set
{
    ll head[N], next[N], X[N], val[N], tot;
    void clear()
    {
        memset(head, 0, sizeof(head));
        memset(next, 0, sizeof(next));
        memset(val, -1, sizeof(val));
        memset(X, 0, sizeof(X));
        tot = 0;
    }
    ll& operator [](ll x)
    {
        ll index = x%N;
        for (ll i = head[index]; i; i = next[i])
        {
            if (X[i] == x)
                return val[i];
        }
        next[++tot] = head[index];
        head[index] = tot;
        X[tot] = x;
        return val[tot];
    }
}hash;
ll pow(ll x, ll y, ll mod)
{
    ll ret = 1;
    while (y)
    {
        if (y & 1)
            ret = ret*x%mod;
        x = x*x%mod;
        y >>= 1;
    }
    return ret;
}
ll gcd(ll a, ll b)
{
    ll t = a%b;
    while (t)
    {
        a = b, b = t;
        t = a%b;
    }
    return b;
}
void exgcd(ll a, ll b, ll &x, ll &y)
{
    if (!b)
        x = 1, y = 0;
    else
    {
        exgcd(b, a%b, y, x);
        y -= a / b*x;
    }
}
ll inv(ll t, ll mod)
{
    ll x, y;
    exgcd(t, mod, x, y);
    return (x%mod + mod) % mod;
}
ll BSGS(ll A, ll B, ll C)
{
    hash.clear();
    ll bk = ceil(sqrt(C)), i, j, k, D, temp;
    for (i = 0, D = 1; i < bk; i++, D = D*A%C)
    {
        if (hash[D] == -1)
            hash[D] = i;
    }
    temp = inv(D, C);
    for (i = 0, k = B; i <= bk; i++, k = k*temp%C)
    {
        if (hash[k] != -1)
            return i*bk + hash[k];
    }
    return -1;
}
ll EXBSGS(ll A, ll B, ll C)
{
    if(C==1)
    {
        if(!B)  return 0;
        else    return -1;
    }
    ll lg = ceil(log(C*1.0) / log(2)), i, k, mod;
    for (i = 0, k = 1; i <= lg; i++, k = k*A%C)
    {
        if (k == B)
            return i;
    }
    i = 0, mod = C;
    while ((k = gcd(A, mod)) != 1)
    {
        if (B%k)    return -1;
        B /= k, mod /= k;
        i++;
    }
    ll ret = BSGS(A, B*inv(pow(A, i, mod)*inv(C / mod, mod) % mod, mod) % mod, mod);
    if (ret != -1)
        return ret + i;
    else
        return -1;
}
int main()
{
    ll c, T, A, B, C, ans;
    scanf("%lld", &T);
    for (c = 1; c <= T; c++)
    {
        scanf("%lld%lld%lld", &A, &C, &B);
        ans = EXBSGS(A, B, C);
        printf("%lld\n", ans);
    }
    return 0;
}
 
时间: 2024-11-05 13:38:03

bzoj-1467 clever Y / JDFZ-2940 EXBSGS的相关文章

【BZOJ1467/2480】Pku3243 clever Y/Spoj3105 Mod EXBSGS

[BZOJ1467/2480]Pku3243 clever Y/Spoj3105 Mod Description 已知数a,p,b,求满足a^x≡b(mod p)的最小自然数x. Input 每个测试文件中最多包含100组测试数据. 每组数据中,每行包含3个正整数a,p,b. 当a=p=b=0时,表示测试数据读入完全. Output 对于每组数据,输出一行. 如果无解,输出“No Solution”(不含引号),否则输出最小自然数解. Sample Input 5 58 33 2 4 3 0 0

BZOJ 3243 Clever Y

Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, Y, Z, we all know how to figure out K fast. However, given X, Z, K, could you figure out Y fast? Input Input data consists of no more than 20 test ca

【EXT-BSGS算法求离散对数】POJ Clever Y 3243

Clever Y Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7259 Accepted: 1795 Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, Y, Z, we all know how to figure out K fast. However, given X,

POJ 3243 Clever Y BSGS

Clever Y Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6861   Accepted: 1676 Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, Y, Z, we all know how to figure out K fast. However, give

poj 3243 Clever Y 高次方程

1 Accepted 8508K 579MS C++ 2237B/** 2 hash的强大,,还是高次方程,不过要求n不一定是素数 3 **/ 4 #include <iostream> 5 #include <cstdio> 6 #include <cmath> 7 #include <cstring> 8 #include <algorithm> 9 using namespace std; 10 long long a,b,n; 11 co

Clever Y POJ - 3243 (扩展BSGS)

Clever Y POJ - 3243 题意:给a,c,b,求最小的x使得 ax≡b (mod c). 扩展BSGS算法~ 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 const int mod=99991; 8 ll head[mod],nex

BZOJ 1467 Pku3243 clever Y EXBSGS

题意:链接 方法: EXBSGS 解析: 这题与BSGS不同的地方就是模数可能不是质数了. 那怎么办呢? 其实也没什么,就是我们不断地分解A和当前的C的最大公约数,注意是当前的C. 假设我们最多分出来了K个最大公约数. Akd1?d2-?dk?Ax?k=Bd1?d2-?dk(modCd1?d2-?dk) 那么怎么做呢? 首先暴力枚举[0,logC]的值是否可以成为解. 为什么取log呢?因为每一次拿出来的最大公约数一定是大于1的,也就是说我们至多拿出来了logC个数,此时的k就是logC,而我们

【数论】【ex-BSGS】poj3243 Clever Y

用于求解高次同余方程A^x≡B(mod C),其中C不一定是素数. http://blog.csdn.net/tsaid/article/details/7354716 这篇题解写得最好. 那啥,这题的坑点请去看discuss. #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; vo

MOD - Power Modulo Inverted(SPOJ3105) + Clever Y(POJ3243) + Hard Equation (Gym 101853G ) + EXBSGS

思路: 前两题题面相同,代码也相同,就只贴一题的题面了.这三题的意思都是求A^X==B(mod P),P可以不是素数,EXBSGS板子题. SPOJ3105题目链接:https://www.spoj.com/problems/MOD/ POJ3243题目链接:http://poj.org/problem?id=3243 题目: 代码实现如下: 1 #include <set> 2 #include <map> 3 #include <queue> 4 #include