【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)的最小非负整数。

Input

输入包含多组数据。

第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。

以下行每行包含三个正整数y,z,p,描述一个询问。

Output

对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。

题目链接:

题意:中文题。。。

1.快速幂

while(T--)
    {
        scanf("%lld%lld%lld",&aa,&bb,&p);
        long long ans=1;
        while(bb>0)
        {
            if(bb&1) ans=ans*aa%p;
            aa=aa*aa%p;
            bb>>=1;
        }
        printf("%lld\n",ans);

    }

2.扩展欧几里德解线性同余方程 ax=b(mod n)

while(T--)
    {
        long long x,y;
        long long d;
        scanf("%lld%lld%lld",&aa,&bb,&p);
        ex_gcd(aa,p,d,x,y);
        if(bb%d!=0)
        {
            printf("Orz, I cannot find x!\n");
            continue;
        }
            x=x*(bb/d)%p;
                x=(x%(p/d)+p/d)%(p/d);
        printf("%lld\n",x);
    }

3.高次同余方程a^x=b(mod n),Baby Step Giant Step算法::

while(T--)
    {
        flag=0;
        long long x,y;
        long long d;
        scanf("%lld%lld%lld",&aa,&bb,&p);

        aa%=p;
        if(!aa&&!bb)
        {
            printf("1\n");
            continue;
        }
        if(!aa)
        {
            printf("Orz, I cannot find x!\n");
            continue;
        }
        mp.clear();
        long long m=ceil(sqrt(p)),t=1;
        mp[1]=m+1;
        for(long long i=1;i<m;i++)
        {
            t=t*aa%p;
            //cout<<t<<"      "<<i<<endl;
            if(!mp[t]) mp[t]=i;
            //cout<<"   "<<mp[1]<<endl;
        }
        //cout<<"SB"<<endl;
        long long tmp=cheng(aa,p-m-1,p),ine=1;
        //cout<<" "<<tmp<<endl;
        //cout<<"SB"<<endl;
        for(long long k=0;k<m;k++)
        {
            //cout<<bb<<"   "<<ine<<endl;
            int i=mp[bb*ine%p];
            //cout<<k<<"   "<<i<<endl;
            if(i)
            {
                flag=1;
                if(i==m+1) i=0;
                printf("%lld\n",k*m+i);
                break;
            }
            ine=ine*tmp%p;
        }
        if(!flag)
        printf("Orz, I cannot find x!\n");
    }
}

思路

———–三个模版…………..

说一下a^x=b(mod n)的Baby Step Giant Step算法(一点分块的思想)

m取sqrt(p);

求y^x=z(mod p)设x=km+i

y^km?y^i≡z

yi≡z?ine(y^km)(逆元)

用费马小定理

y^(p-1)mod p=1;

y^m * y^(p-m-1) mod p =1;

y^m的逆元为y^(p-m-1)

ine(y^m)≡y^(p?1?m)

设其为T

ine(y^km)≡ine(y^(k?1)m)?T

把y^i(0<=i<=m)放入map;

然后枚举k,查询

z?ine(y^km)

代码

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<map>
using namespace std;
int T,k;
int flag=0;
long long  aa,bb,p;
map<int,int> mp;
void solve1()
{
    while(T--)
    {
        scanf("%lld%lld%lld",&aa,&bb,&p);
        long long ans=1;
        while(bb>0)
        {
            if(bb&1) ans=ans*aa%p;
            aa=aa*aa%p;
            bb>>=1;
        }
        printf("%lld\n",ans);

    }

}
void ex_gcd(long long a,long long b,long long &d,long long &x,long long &y)
{
    if(b==0)
    {
        x=1,y=0;
        d=a;
        return ;
    }
    ex_gcd(b,a%b,d,x,y);
    long long  x0=x;
    x=y;
    y=x0-(a/b)*y;

}
void solve2()
{
    while(T--)
    {
        long long x,y;
        long long d;
        scanf("%lld%lld%lld",&aa,&bb,&p);
        ex_gcd(aa,p,d,x,y);
        if(bb%d!=0)
        {
            printf("Orz, I cannot find x!\n");
            continue;
        }
            x=x*(bb/d)%p;
                x=(x%(p/d)+p/d)%(p/d);
        printf("%lld\n",x);
    }

}
long long cheng(long long a,long long b,long long p)
{
    long long ans=1;
    while(b>0)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans;
}
void solve3()
{
    while(T--)
    {
        flag=0;
        long long x,y;
        long long d;
        scanf("%lld%lld%lld",&aa,&bb,&p);

        aa%=p;
        if(!aa&&!bb)
        {
            printf("1\n");
            continue;
        }
        if(!aa)
        {
            printf("Orz, I cannot find x!\n");
            continue;
        }
        mp.clear();
        long long m=ceil(sqrt(p)),t=1;
        mp[1]=m+1;
        for(long long i=1;i<m;i++)
        {
            t=t*aa%p;
            //cout<<t<<"      "<<i<<endl;
            if(!mp[t]) mp[t]=i;
            //cout<<"   "<<mp[1]<<endl;
        }
        //cout<<"SB"<<endl;
        long long tmp=cheng(aa,p-m-1,p),ine=1;
        //cout<<" "<<tmp<<endl;
        //cout<<"SB"<<endl;
        for(long long k=0;k<m;k++)
        {
            //cout<<bb<<"   "<<ine<<endl;
            int i=mp[bb*ine%p];
            //cout<<k<<"   "<<i<<endl;
            if(i)
            {
                flag=1;
                if(i==m+1) i=0;
                printf("%lld\n",k*m+i);
                break;
            }
            ine=ine*tmp%p;
        }
        if(!flag)
        printf("Orz, I cannot find x!\n");
    }
}
int main()
{

    scanf("%d%d",&T,&k);
    if(k==1) solve1();
    if(k==2) solve2();
    if(k==3) solve3();
}
时间: 2024-08-09 10:44:23

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

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

总结——数论:欧几里得算法&amp;扩展欧几里得证明

一 欧几里得辗转相除法算法 设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),又因 r = a mod b,所以 gcd(a,b)=gcd(b,a mod b). 证明:①证明充分性. 设 d 为 a,b 的公约数,记作 d|a , d|b ,即a和b都可以被d整除 又因 r=a-kb , 两边同时除以d,r/d=a/d-kb/d=m,由等式右边可知m为整数, d|r , 即 d 是 (b,a mod b)的公约数, ②证明必要性 设 d 为 b, a mod b

P2485 [SDOI2011]计算器(快速幂+扩欧+bsgs)

题目描述 你被要求设计一个计算器完成以下三项任务: 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最小非负整数x: 3.给定y.z.p,计算满足y^x ≡z(mod p)的最小非负整数x. 为了拿到奖品,全力以赴吧! 输入输出格式 输入格式: 输入文件calc.in 包含多组数据. 第一行包含两个正整数T.K,分别表示数据组数和询问类型(对于一个测试点内的所有数 据,询问类型相同). 以下T 行每行包含三个正整数y.z.p,描述一个询问

AHOI 2005--洗牌(扩展欧几里得&amp;快速幂)

发现BZOJ上也是有不少水题的哦! 排名进前3000也是很容易的哦! 然后就要继续刷题了哦! 题意 为了表彰小联为Samuel星球的探险所做出的贡献,小联被邀请参加Samuel星球近距离载人探险活动. 由于Samuel星球相当遥远,科学家们要在飞船中度过相当长的一段时间,小联提议用扑克牌打发长途旅行中的无聊时间.玩了几局之后,大家觉得单纯玩扑克牌对于像他们这样的高智商人才来说太简单了.有人提出了扑克牌的一种新的玩法. 对于扑克牌的一次洗牌是这样定义的,将一叠N(N为偶数)张扑克牌平均分成上下两叠

URAL 1141. RSA Attack(欧拉定理+扩展欧几里得+快速幂模)

题目链接 题意 : 给你n,e,c,并且知道me ≡ c (mod n),而且n = p*q,pq都为素数. 思路 : 这道题的确与题目名字很相符,是个RSA算法,目前地球上最重要的加密算法.RSA算法原理 . 看到这个算法之后,就知道这个题是求cd≡m(mod n),要求m,就要先求d,而d则是e的模反元素. 如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1.这时,b就叫做a的模反元素. 由模反元素可知,ed≡1(mod Phi[n])(p

POJ 2154 Color(组合数学-波利亚计数,数论-欧拉函数,数论-整数快速幂)

Color Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7693   Accepted: 2522 Description Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of th

POJ 1995 Raising Modulo Numbers (数论-整数快速幂)

Raising Modulo Numbers Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4379   Accepted: 2516 Description People are different. Some secretly read magazines full of interesting girls' pictures, others create an A-bomb in their cellar, oth

[ACM] hdu 3923 Invoker (Poyla计数,快速幂运算,扩展欧几里得或费马小定理)

Invoker Problem Description On of Vance's favourite hero is Invoker, Kael. As many people knows Kael can control the elements and combine them to invoke a powerful skill. Vance like Kael very much so he changes the map to make Kael more powerful. In

【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到Catalan数,但是我却花了两个小时去找递推式. 首先 Catalan数 : 基本规律:1,2,5,14,42,132,.......... 典型例题: 1.多边形分割.一个多边形分为若干个三角形有多少种分法. C(n)=∑(i=2...n-1)C(i)*C(n-i+1) 2.排队问题:转化为n个人