zoukankan      html  css  js  c++  java
  • Bzoj 2242: [SDOI2011]计算器(BSGS)

    2242: [SDOI2011]计算器
    Time Limit: 10 Sec Memory Limit: 512 MB
    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”之间有一个空格。
    Sample Input
    【样例输入1】
    3 1
    2 1 3
    2 2 3
    2 3 3
    【样例输入2】
    3 2
    2 1 3
    2 2 3
    2 3 3
    【数据规模和约定】
    对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。
    Sample Output
    【样例输出1】
    2
    1
    2
    【样例输出2】
    2
    1
    0
    HINT
    Source
    第一轮day1

    /*
    复合题hhh.
    前两问裸的快速幂 exgcd.
    读入int64 不要图快用scanf linux好像不行? 
    然后这题case 3 是BSGS.
    由于本人比较弱
    所以我只能感性的认识一下BSGS.
    y^x≡z(mod p).
    这题暴力的话复杂度是O(p)的.
    因为根据费马小定理y^(p-1)≡1(mod p).
    剩余系元素的个数就是p-1,再往后就出现循环了.
    然后我们采用分块的思想,令m=√p.
    然后就有y^(km+i)≡z(mod p).
    y^i≡ine(y^km)*z(mod p) (ine x为x的逆元).
    然后左边hash存表,右边枚举k.
    逆元是积性函数.
    右边就变成了ine(y^m(k-x))*[ine(y^m)]^x.
    枚举k即可.
    然后因为费马小定理有y^m*y^(p-m-1)≡1(mod p).
    so ine(y^m)=y^(p-m-1).
    复杂度就变成了O(sqrt(p)).
    */
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<map>
    #define LL long long
    using namespace std;
    int k,t,n,p;
    LL a,b,x,y,c;
    map<int ,int >s;
    LL mi()
    {
        LL tot=1;
        while(b)
        {
            if(b&1) tot=tot*a%p;
            a=a*a%p;
            b>>=1;
        }
        return tot%p;
    }
    void slove1()
    {
        while(t--)
        {
            cin>>a>>b>>p;// 1 W.
            //scanf("%lld%lld%lld",&a,&b,&p);
            printf("%lld
    ",mi());
        }
    }
    void exgcd(LL a,LL b,LL &x,LL &y)
    {
        if(!b) {x=1,y=0;return;}
        else exgcd(b,a%b,y,x),y-=(a/b)*x;
    }
    void slove2()
    {
        while(t--)
        {
            cin>>a>>c>>b;
            LL g=__gcd(a,b);
            if(c%g) printf("Orz, I cannot find x!
    ");
            else
            {
                x=y=0;
                exgcd(a,b,x,y);
                x*=c;g=b/g;
                x=(x%g+g)%g;
                cout<<x<<endl;
            }
        }
    }
    LL mi1(LL aa,LL bb,LL pp)
    {
        LL tot=1;
        while(bb)
        {
            if(bb&1) tot=tot*aa%pp;
            aa=aa*aa%pp;
            bb>>=1;
        }
        return tot%pp;
    }
     map<int,int> mp;
    void slove3()
    {
        int ans=0,y,z;
        bool flag=false;
        while(t--)
        {
            scanf("%d%d%d",&y,&z,&p);y%=p;
            if (!y&&!z) {printf("1
    ");continue;}
            if (!y){printf("Orz, I cannot find x!
    ");continue;}
            s.clear();
            LL m=ceil(sqrt(p)),tot=1;s[1]=m+1;
            for(int i=1;i<=m-1;i++)
            {
                tot=tot*y%p;
                if(!s[tot]) s[tot]=i;
            }
            bool flag=false;
            LL tmp=mi1(y,p-1-m,p),ni=1;//2 W.
            for(int k=0;k<=m-1;k++)
            {
                int i=s[z*ni%p];
                if(i)
                {
                    if(i==m+1) i=0;
                    flag=true;printf("%d
    ",k*m+i);break;
                }
                ni=ni*tmp%p;
            }
            if(!flag) printf("Orz, I cannot find x!
    ");
        }
        return ;
    }
    int main()
    {
    
        scanf("%d%d",&t,&k);
        if(k==1) slove1();
        else if(k==2) slove2();
        else slove3();
        return 0;
    }
  • 相关阅读:
    C++之Static与Const
    LInux主机与虚拟机网络链接
    C#数据类型与数据类型转化
    C#网编Console(二)
    C#网编Winform(三)
    C#网编基础类与API(一)
    C实现CPU大小端判断
    QT程序图标设置
    四、初识Socket套接字API
    C++之继承(二)
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068102.html
Copyright © 2011-2022 走看看