码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-08-30 19:17:25      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

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

于是就要知道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;
}

 

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

标签:

原文地址:http://www.cnblogs.com/sagitta/p/4771307.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!