zoukankan      html  css  js  c++  java
  • BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)

    污污污污
    

    2242: [SDOI2011]计算器
    Time Limit: 10 Sec Memory Limit: 512 MB
    Submit: 2312 Solved: 917
    [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”之间有一个空格。

    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

    第一问:快速幂直接搞;
    第二问:拓展欧几里得直接搞;
    第三问:BSGS直接搞;
    

    安利一下BSGS的大体框架:
    首先要求 a^x=b (mod c)
    假定x=im-j (m=ceil(sqrt(n)))
    那么进行变换:
    a^im = b*a^j (mod c)
    枚举b*a^j mod p的值存入哈希表(map)。
    再枚举a^im的值,从哈希表里找,如果能找到一样的答案就是i*m-j

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    
    using namespace std;
    int n;
    
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int gcd(int a,int b)
    {
        if (!b) return a;
           else return gcd(b,a%b);
    }
    
    void exgcd(int a,int b,int &x,int &y)
    {
        if (!b) {x=1,y=0;return;}
        exgcd(b,a%b,x,y);
        int t=x;x=y;
        y=t-a/b*y;
    }
    
    long long quick_pow(long long a,int b,int p)//返回a^b%p的值
    {
        long long re=1;
        long long tmp=a%p;
        while (b)
            {
                if (b&1)
                    re=(re*tmp)%p;
                tmp=(tmp*tmp)%p;
                b=b>>1;
            }
        return re;
    }
    
    
    void work1(int a,int b,int c) 
    {
        printf("%lld
    ",quick_pow(a,b,c));
    }
    void work2(int a,int b,int c) 
    { 
        c=-c;
        int gc=gcd(a,c); 
        if (b%gc!=0) {puts("Orz, I cannot find x!");return;}
        a/=gc;b/=gc;c/=gc;
        int x,y;exgcd(a,c,x,y);
        x=(long long)x*b%c;
        while (x<0) x+=c;
        printf("%d
    ",x);
    }
    void work3(int a,int b,int c)
    {
        map<int,int>mp;mp.clear();
        if (a%c==0) {puts("Orz, I cannot find x!");return;}
        int m=ceil(sqrt(c));
        long long t=b;
        for (int i=0; i<=m; i++)
            {
                mp[(int)t]=i;
                t=t*a%c;
            }
        int s=quick_pow(a,m,c);t=s;
        for (int i=1; i<=m; i++)
            {
                int v=mp[(int)t];
                if (v!=0) {printf("%d
    ",i*m-v);return;}
                t=t*s%c; 
            }
        puts("Orz, I cannot find x!");
    }
    
    int main()
    {
        int t=read(),k=read();
        for (int i=1; i<=t; i++)
            {
                int y=read(),z=read(),p=read();
                if (k==1) work1(y,z,p);
                if (k==2) work2(y,z,p);
                if (k==3) work3(y,z,p);
            }
        return 0;
    }
  • 相关阅读:
    Linux中chown和chmod的区别和用法(转)
    一个小时学会Git
    核心团队的信任和默契——超越管理
    一个项目怎么开发出来
    产品经理职责
    从技术到管理:思维转变是关键
    可扩展Web架构与分布式系统
    浅谈大型web系统架构
    亿级Web系统搭建——单机到分布式集群
    Docker容器进入的4种方式
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346201.html
Copyright © 2011-2022 走看看