bzoj3929 Discrete Logging 大步小步算法

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
ll p,a,b;
ll ksm(ll x,ll y)
{
    ll res=1;
    while(y) {
        if(y&1)res=res*x%p;
        y>>=1;
        x=x*x%p;
    }
    return res;
}
map<ll,ll> h;
ll solve(ll a,ll b,ll p)
//设x=im-c,则x+c=im
//a^x * a^c =a^im
{
    ll m=ceil(sqrt(p));//向上取整
    h.clear();
    for(ll i=0; i<m; i++)
    //求出b*a,b*a^2,b*a^3...即等式左边那一段,放到map中
	{
        if(!h.count(b))
		   h[b]=i;
        b=b*a%p;
    }
    ll now=1,base=ksm(a,m);
    for(ll i=1; i<=m+1; i++)
    //枚举i,算a^im的结果,然后到hash表中去找
	{
        now=now*base%p;
        if(h.count(now))return i*m-h[now];
    }
    return -1;
}
int main()
{
    while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
	{
        ll ans=solve(a,b,p);
        if(ans==-1)printf("no solution\n");
        else printf("%lld\n",ans);
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
pair<long long, long long> x[1000001];
long long p, b, n;
long long pow(long long x, long long y, long long p)
{
    long long ans = 1;
    while(y)
	{
        if(y & 1) ans *= x, ans %= p;
        y >>= 1;
        x *= x;
        x %= p;
    }
    return ans;
}

long long find(long long l, long long r, long long v)
{
    while(l <= r)
	{
        long long mid = (l + r) / 2;
        if(x[mid].first < v)
		{
            l = mid + 1;
        }
        else{
            r= mid-1;
        }
    }
    return (x[l].first == v) ? l : -1;
}

int main()
{
    cin >> p >> b >> n;
	//b^x =N % p
   long long sq = (double)(sqrt(p - 2) + 0.5);

    x[0].first = 1;
    x[0].second = 0;
    for(long long i = 1; i < sq; ++i)
    //求出b的若干次方Mod P的结果,放到一个表里
	{
        x[i].first = x[i - 1].first * b;
        x[i].first %= p;
        x[i].second = i;
    }
    sort(x, x + sq - 1);//排序
    for(long long i = 0; i <= sq; ++i)
	{
        long long v = n * pow(b, p - 1 - i * sq, p);
        v %= p;
        long long j = find(0, sq - 1, v);//到表里去找
        if(j != -1)
		{
            cout << i * sq + x[j].second << endl;
            return 0;
        }
    }
    cout << "no solution" << endl;
    return 0;
}

  

原文地址:https://www.cnblogs.com/cutemush/p/11990960.html

时间: 2024-08-10 20:24:30

bzoj3929 Discrete Logging 大步小步算法的相关文章

【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线代算法我也不想多说,还是自行百度吧 需要注意的是矩阵没有交换律,所以在计算$B\cdot A^{-m}$的时候不要把顺序搞混 代码: 1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 #inc

BSGS算法学习小记(大步小步算法)

简介 先看一个式子xy≡z(modp),z是质数 现在只知道x和z,要求y. 大步小步算法(BSGS,Baby Steps Giant Steps)就是解决这个问题. 算法流程 暴搜的枚举范围 根据费马小定理:xz?1≡1. 如果y已经枚举到了z-1了,继续枚举的话就会产生循环. 所以,在暴搜中y的枚举范围就是0--z-1. 如何优化暴搜 我们想一想可不可以用分块来解决枚举的y. 把y分成p?1????√分别枚举行不行? 设m=p?1????√,y=a?m+b,这样枚举a和b就相当于分块枚举了.

uva 11916 - Emoogle Grid(大步小步算法)

题目连接:uva 11916 - Emoogle Grid 题目大意:有一问题,在M行N列的网格上涂K种颜色,其中有B个格子不用涂色,其它每个格子涂一种颜色,同一列的上下两个相邻的格子不能涂相同的颜色.给出M,N,K和B个格子的位置,求出总方案数模掉1e8+7的结果R.现在已知R,求最小的M. 解题思路:有确定不用涂色格子的区域作为不变部分,总数通过计算为tmp,外加可变部分的第一行,方案数为cnt,可变部分除第一行外,每加一行都将总数乘以(K?1)N,既有 cnt?PM=Rmod(1e8+7)

UVA 11916 Emoogle Grid 离散对数 大步小步算法

LRJ白书上的题 #include <stdio.h> #include <iostream> #include <vector> #include <math.h> #include <set> #include <map> #include <queue> #include <algorithm> #include <string.h> #include <string> using

Shank的大步小步算法(Shank‘s Baby-Step-Giant-Step Algorithm)

1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <map> 5 typedef long long LL; 6 int mul_mod(int a,int b,int n){ // a.b都小于n 7 return a * b % n; 8 } 9 int pow_mod(int a,int p,int n){ 10 if(p == 0) return 1; 11

BSGS算法(大步小步算法)

计算\(y^x ≡ z \ mod\ p\) 中 \(x\) 的解. 这个模板是最小化了\(x\) , 无解输出\(No \ Solution!\) map<ll,ll>data; ll m,res,t,ans; bool flag; Pow(int x,int y,int p){return (x^y)%p;} IL void BSGS(RG ll y , RG ll z,RG ll p){ y %=p; flag = false; if(!y && !z){puts(&qu

大步小步算法 模板bzoj 计算器

你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数. code: // #include<bits/stdc++.h> using namespace std; #define ll long long ll T,p; ll ksm(ll a,ll b,ll c) { ll ans=1; while(b

POJ2417 Discrete Logging

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the disc

BSGS算法+逆元 POJ 2417 Discrete Logging

POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accepted: 2211 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarith