bzoj2242: [SDOI2011]计算器 && BSGS 算法

BSGS算法

给定y、z、p,计算满足yx mod p=z的最小非负整数x。p为质数(没法写数学公式,以下内容用心去感受吧)

x = i*m + j.

y^(j)≡z?y^(-i*m)) (mod p)

y^(j)≡z?ine(y^(i*m)) (mod p)(逆元)

由费马小定理y^(p-1)≡1 (mod p) ine(y^m) = y^(p-m-1) 

ine(y^(i*m)≡ine(y^((i?1)m))?y^(p-m-1) 

1.首先枚举同余符号左面,用一个hash保存(y^j,j),因为j可能等于0,所以hash[1]要赋为一个特殊值。

2.再枚举同余符号右面,如果hash(z?ine(y^(i*m)))存在,就找到了一组解。

显然,m=sqrt(p)的时候复杂度最低为O(sqrt(p)),m=ceil(sqrt(p)).

从这个人博客中可以看出,这个人对于BSGS算法有着相当深刻的理解,居然能够找到俩个有助于学习BSGS算法的俩首歌,还用了exgcd算法。

http://www.cnblogs.com/yuiffy/p/3877381.html

 

其他俩个操作为快速幂,exgcd。

因为题目并不是一起写的,所以写了俩个快速幂。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;

int T,k;
long long y,z,p;
map<int,int> hash;

long long q(long long z) {
    if(z==1) return y%p;
    long long m=q(z/2);
    if(z%2) return (((m*m)%p)*y)%p;
    return (m*m)%p;
}

void solve1() {
    printf("%lld\n",q(z));
}

long long exgcd(long long a,long long b,long long &x,long long &y) {
    if(b==0) {
        x=1; y=0;
        return a;
    }
    long long res=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return res;
}

void solve2(long long a,long long b,long long n) {
    long long x,y,ans,d,s;
    d=exgcd(a,n,x,y);
    if(b%d!=0) printf("Orz, I cannot find x!\n");
    else {
        ans=(b/d)*x; s=n/d;
        ans=(ans%s+s)%s;
        printf("%lld\n",ans);
    }
}

long long power(long long a,long long b,long long mod) {
    long long res=1;
    while(b) {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

void solve3() {
    y%=p; z%=p;
    if(!y && !z) printf("1\n");
    else if(!y) printf("Orz, I cannot find x!\n");
    else {
        long long m,v,e,res;
        m=ceil(sqrt(p)); v=power(y,p-m-1,p); e=1;    

        hash.clear();
        hash[1]=m+1;
        for(long long i=1;i<=m;i++) {
            e=e*y%p;
            if(!hash[e]) hash[e]=i;
        }

        res=-1;
        for(long long i=0;i<m;i++) {
            if(hash[z]) {
                res=i*m+(hash[z]==m+1?0:hash[z]);
                break;
            }
            z=z*v%p;
        }
        if(res==-1) printf("Orz, I cannot find x!\n");
        else printf("%d\n",res);
    }
}

int main() {
    scanf("%d%d",&T,&k);
    while(T--) {
        scanf("%lld%lld%lld",&y,&z,&p);
        if(k==1) solve1();
        else if(k==2) solve2(y,z,p);
        else solve3();
    }
    return 0;
}
时间: 2024-10-24 21:55:26

bzoj2242: [SDOI2011]计算器 && BSGS 算法的相关文章

bzoj2242: [SDOI2011]计算器 BSGS+exgcd

你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值:(快速幂) 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数:(exgcd) 3.给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数.(BSGS) /************************************************************** Problem: 2242 User: walfy Language: C++ Resu

bzoj 2242: [SDOI2011]计算器 &amp; BSGS算法笔记

这题的主要难点在于第三问该如何解决 于是就要知道BSGS是怎样的一种方法了 首先BSGS是meet in the middle的一种(戳下面看) http://m.blog.csdn.net/blog/zentropy/11200099 看完链接后再看以下内容 --------------------------------------------------------------------------------------------------------------------- 对

[bzoj2242][Sdoi2011]计算器_exgcd_BSGS

计算器 bzoj-2242 Sdoi-2011 题目大意:裸题,支持快速幂.扩展gcd.拔山盖世 注释:所有数据保证int,10组数据. 想法:裸题,就是注意一下exgcd别敲错... ... 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <ma

bzoj2242: [SDOI2011]计算器.

2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4353  Solved: 1679[Submit][Status][Discuss] Description 你被要求设计一个计算器完成以下三项任务: 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)的最小非负整数. In

BZOJ 2242 [SDOI2011]计算器 BSGS+快速幂+EXGCD

题意:链接 方法: BSGS+快速幂+EXGCD 解析: BSGS- 题解同上.. 代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MOD 140345 using namespace std; typedef long long ll; ll t,k,ans; ll y,z,p;

bzoj千题计划246:bzoj2242: [SDOI2011]计算器

http://www.lydsy.com/JudgeOnline/problem.php?id=2242 #include<map> #include<cmath> #include<cstdio> using namespace std; int y,z,p; map<int,int>mp; int Pow(int a,int b,int m) { int ans=1; for(;b;a=1LL*a*a%m,b>>=1) if(b&1)

【bzoj2242】[SDOI2011]计算器 数论相关(快速幂+扩展欧几里得+BSGS)

2242: [SDOI2011]计算器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2529 Solved: 1003 [Submit][Status][Discuss] Description 你被要求设计一个计算器完成以下三项任务: 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)的最小非负整数. In

BZOJ 2242: [SDOI2011]计算器( 快速幂 + 扩展欧几里德 + BSGS )

没什么好说的... --------------------------------------------------------------------- #include<cstdio> #include<cmath> #include<map> using namespace std; typedef long long ll; int MOD; void gcd(int a, int b, int& d, int& x, int& y)

【bzoj2242】[SDOI2011]计算器

2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3207  Solved: 1258[Submit][Status][Discuss] Description 你被要求设计一个计算器完成以下三项任务: 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)的最小非负整数. In