大步小步算法 模板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)
    {
        if(b&1) ans=(ans*a)%c;
        b>>=1;
        a=(a*a)%c;
    }
    return ans;
}
map <ll,ll> mapp;
ll BSGS (ll a,ll b,ll c)
{
    if(!a) return b? -1:1;
    if(b==1) return 0;
    mapp.clear();
    ll ax=1;
    ll m=ceil(sqrt(c));
    for(int i=0;i<m;i++)
    {
        mapp[ax]=i;
        ax=(ax*a)%c;
    }
    ll am=ksm(a,m,c);
    for(int i=1;i<=m;i++)
    {
        if(mapp.count((am*ksm(b,c-2,c))%c)) return i*m-mapp[(am*ksm(b,c-2,c))%c];
        am=(am*ksm(a,m,c))%c;
    }
    return -1;
}
int main()
{
    cin>>T;
    ll y , z , d;
    scanf("%lld",&p);
    while(T--)
    {

        if(p==1)
        {
            scanf("%lld%lld%lld",&y,&z,&d);
            printf("%lld\n",ksm(y,z,d));
        }else
        if(p==2)
        {
            scanf("%lld%lld%lld",&y,&z,&d);
            if(y%d==0) puts("Orz, I cannot find x!");
            else
            printf("%lld\n",(ksm(y,d-2,d)*z)%d);
        }else
        if(p==3)
        {

            scanf("%lld%lld%lld",&y,&z,&d);
            ll ans=BSGS(y%d,z%d,d);
            if(~ans)
            printf("%lld\n",ans);
            else
            puts("Orz, I cannot find x!");
        }
    }

 } 

原文地址:https://www.cnblogs.com/OIEREDSION/p/11330034.html

时间: 2024-08-27 07:23:28

大步小步算法 模板bzoj 计算器的相关文章

【题解】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)

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

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

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<l

tarjan算法模板

var {left表示点 root 没离开栈 vis表示点 root 有没有被访问过} i,n,m,now,time,color,top:longint; v:array[0..10001] of record start:longint;end; e:array[0..100001] of record y,next:longint;end; dfn,low,stack,encolor:array[0..10001] of longint; vis,left:array[0..10001] o

prim算法模板

var g:array[1..10,1..10] of longint; d:array[1..10] of longint; f:array[1..10] of boolean; procedure prim; var i,j,k,min:longint; begin fillchar(g,sizeof(g),0); fillchar(f,sizeof(f),0); for i:=1 to n do d[i]:=g[1,i]; f[1]:=true; for i:=2 to n do begi