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

这题的主要难点在于第三问该如何解决

于是就要知道BSGS是怎样的一种方法了

首先BSGS是meet in the middle的一种(戳下面看)

http://m.blog.csdn.net/blog/zentropy/11200099

看完链接后再看以下内容

---------------------------------------------------------------------------------------------------------------------

对于一个质数p 我们由费马小定理知道y^xmodp最多(p-1)次便是一个循环节

因此如果有解 x一定在0到p-1中

所以我们只需知道x取0到p-1是否有解即可

根据meet in the middle 的思想 令m=sqrt(p-1)

那么我们仅需先求出 0~m-1(如果有解这里就退出)

然后再求出 m,2m,3m……nm(nm<=p-1)

分别询问y^(0~m-1)中是否有和y^km乘起来modp等于z的

然而显然我们这个操作直接做的话 是sqrt(n)*sqrt(n)=n的

所以学过逆元怎么求了之后可以将y^km modp意义下的逆元与z相乘

然后再询问y^(0~m-1)中有没有与它相等的即可

这样去做就是sqrt(n)*hash的复杂度

有手动hash技巧的话 hash复杂度可以看做1

比较懒的话 直接用map来hash就是log(n)

#include <bits/stdc++.h>
using namespace std;
map<int,int> mp;
int solve1(int x,int y,int mod)
{
    long long t=x,re=1;
    while(y)
    {
        if(y&1)
            re=re*t%mod;
        t=t*t%mod;
        y>>=1;
    }
    return (int)re;
}
int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    int t,d;
    d=exgcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-(a/b)*x;
    return d;
}
void solve2(int y,int z,int p)
{
    int x,yy;
    int d=exgcd(y,p,x,yy);
    if(z%d)
    {
        puts("Orz, I cannot find x!");
        return;
    }
    x=(long long)x*(z/d)%p;
    x=(x<0?x+p:x);
    printf("%d\n",x);
}
bool solve3(int y,int z,int p)
{
//  if(z>=p)
//      return 0;
    y%=p;
    if(!y)
    {
        if(z)
            return 0;
        puts("1");
        return 1;
    }
    mp.clear();
    int m=ceil(sqrt(p-1));
    long long t=1;
    for(int i=0;i<m;++i)
    {
        if(t==z)
        {
            printf("%d\n",i);
            return 1;
        }
        if(!mp[t])
            mp[t]=i+1;
        else
            return 0;
        t=t*y%p;
    }
    int inv=solve1(y,p-1-m,p);
    t=z;
    for(int i=m;i<=p-2;i+=m)
    {
        t=t*inv%p;
        if(mp[t])
        {
            printf("%d\n",i+mp[t]-1);
            return 1;
        }
    }
    return 0;
}
int main()
{
    int t,ca,y,z,p;
    scanf("%d%d",&t,&ca);
    while(t--)
    {
        scanf("%d%d%d",&y,&z,&p);
        if(ca==1)
            printf("%d\n",solve1(y,z,p));
        else if(ca==2)
            solve2(y,z,p);
        else if(ca==3)
            if(!solve3(y,z,p))
                puts("Orz, I cannot find x!");
    }
    return 0;
}
时间: 2024-10-10 12:30:21

bzoj 2242: [SDOI2011]计算器 & BSGS算法笔记的相关文章

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

bzoj 2242 [SDOI2011]计算器(数论知识)

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)的最小非负整数. Input 输入包含多组数据. 第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同). 以下行每行包含三个正整数y,z,p,描述一个询问. Output 对于每个询问,输出一行答案.对

bzoj2242: [SDOI2011]计算器 &amp;&amp; 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保存

BZOJ 2242 [SDOI2011]计算器(快速幂+Exgcd+BSGS)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2242 [题目大意] 给出T和K 对于K=1,计算 Y^Z Mod P 的值 对于K=2,计算满足 xy≡ Z ( mod P ) 的最小非负整数 对于K=3,计算满足 Y^x ≡ Z ( mod P) 的最小非负整数 [题解] K=1情况快速幂即可 K=2情况用exgcd求解 K=3用BSGS求解 [代码] #include <cstdio> #include <cmath&

BZOJ 2242 SDOI2011 计算器 快速幂+扩展欧几里得+BSGS

题目大意:--简洁明了自己看 第一问快速幂 第二问扩展欧几里得 第三问BSGS 顺便一开始没看到p是质数0.0 去弄了EXBSGS的模板0.0 懒得改了 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1001001 using namespace std; typedef long long l

[原博客] BZOJ 2242 [SDOI2011] 计算器

题目链接 noip级数论模版题了吧.让求三个东西: 给定y,z,p,计算Y^Z Mod P 的值. 给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数. 给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数. 其中P均为素数.来分着处理. 1 y^z%p 快速幂.推荐一种又快又好写的写法. 1 LL power_mod(LL a,LL b,LL p){ //get a^b%p 2 LL ret=1; 3 while(b){ 4 if(b&1) ret = re

【快速幂】【扩展欧几里德】【BSGS】【SDOI 2011】【bzoj 2242】计算器

2242: [SDOI2011]计算器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2077 Solved: 812 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)的最小非负整数. Input 输入包含多组数据. 第一行包含两个正整数T,K

【BZOJ】2242: [SDOI2011]计算器

http://www.lydsy.com/JudgeOnline/problem.php?id=2242 题意:(前两个问略...)第三个问是,求$a^x \equiv b \pmod{p}$,它们范围都是$10^9$哒= = #include <bits/stdc++.h> using namespace std; typedef long long ll; int mpow(ll a, ll b, ll p) { ll r=1; a%=p; while(b) { if(b&1) r