zoukankan      html  css  js  c++  java
  • BZOJ2242 SDOI2011 计算器

    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
     
      这道题就是一道板子合集。
      发现B站样例没有操作3,那么这就很难受。
      但是洛谷和codevs上面有。
      对于操作1,NOIP提高组D1T1难度。
      
      对于操作2,因为有 XY≡Z,由数论姿势可以得到
        X*Y*Y-1≡X≡Z*Y-1(mod p);
      Y-1是指Y的逆元。因为题目说了P为素数,用欧拉定理就可以了。
      对于操作3,离散数对离散对数板子题。
      这一类做法就是套路分块。
      设x=i*m+j。则有:
        Y(i*m+j)≡Z;
      即 Yi*m≡Z*Y-j
      枚举i,则Yi*m可以算出来。假设为K。
      于是就有:
        Z*Y-j≡K (mod p)
      然后像第二问一样把Y-j求出来,看一下[0,m)内有没有解。
      这个东西可以用一个哈希表或者map,set什么的预处理[0,m)的逆元来搞搞。
      所以说m选在√n的时候是最优秀的。
     
      然后因为某很懒,不愿意想太多事,所以把这个算法懒化了一下。
      (这么干的某不是第一个。)
      设x=i*m-j;
      没错最后的式子就是
        Z*Yj≡K (mod p);
      一个小小的改动,就可以不用找逆元了。
      
      最后提一下判断无解的点:
        对于操作2,如果Y=0而Z!=0就一定无解。
        对于操作3,如果Y=0而Z!=0就一定无解。
        对于操作3,找到最后找不到了就是无解了。
      然后我就想知道B站那些时间只要三位数的老爷是什么情况。
      可能操作2用exgcd更优秀吧,真的吗?
      某的3000ms完全没戏啊,应该是卡不下来的?
    #include    <iostream>
    #include    <cstdio>
    #include    <cstdlib>
    #include    <algorithm>
    #include    <vector>
    #include    <cstring>
    #include    <queue>
    #include    <complex>
    #include    <stack>
    #include    <cmath>
    #define LL long long int
    #define dob double
    using namespace std;
     
    const int N = 1000010;
    struct Node{int to,val,next;}E[N];
    int n,type,head[N],tot;
     
    int gi()
    {
      int x=0,res=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
      while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
      return x*res;
    }
     
    inline int QPow(int d,int z,int Mod){
      int ans=1;
      for(;z;z>>=1,d=1ll*d*d%Mod)
        if(z&1)ans=1ll*ans*d%Mod;
      return (ans+Mod)%Mod;
    }
     
    inline void link(int u,int v,int w){
      E[++tot]=(Node){v,w,head[u]};
      head[u]=tot;
    }
     
    inline void work1(){
      while(n--){
        int y=gi(),z=gi(),p=gi();
        printf("%d
    ",QPow(y%p,z%(p-1),p));
      }
      return;
    }
     
    inline void work2(){
      while(n--){
        int y=gi(),z=gi(),p=gi();
        y%=p;z%=p;
        if(!y && z){
          printf("Orz, I cannot find x!
    ");
          continue;
        }
        int x=QPow(y,p-2,p);
        x=1ll*x*z%p;
        printf("%d
    ",x);
      }
      return;
    }
     
    inline void work3(){
      while(n--){
        int y=gi(),z=gi(),p=gi();
        y%=p;z%=p;
        if(!y && z){
          printf("Orz, I cannot find x!
    ");
          continue;
        }      
        int m=sqrt(p),flag=0;
        memset(head,0,sizeof(head));tot=0;
        for(int i=0,d=1;i<m;++i){
          link(d%N,d,i);
          d=1ll*d*y%p;
        }
        for(int i=1;i<=m && !flag;++i){
          int ny=QPow(y,i*m,p);
          int x=QPow(z,p-2,p);
          x=1ll*x*ny%p;
          for(int e=head[x%N];e;e=E[e].next)
            if(E[e].to==x){
              printf("%d
    ",(i*m-E[e].val)%p);
              flag=1;break;
            }
        }
        if(!flag)
          printf("Orz, I cannot find x!
    ");
      }
    }
     
    int main()
    {
      n=gi();type=gi();
      if(type==1)work1();
      if(type==2)work2();
      if(type==3)work3();
      /*fclose(stdin);
        fclose(stdout);*/
      return 0;
    }
    

      

      
  • 相关阅读:
    WIN7每次从关闭屏幕状态恢复都会挂断宽带连接,请问如何解决?
    程序設計学习之路:不走弯路,就是捷径
    Customize Firefox "Close tab" button
    域名常识
    一到十的英文单词,一十二个月份的英文单词,四季的英文单词,第一,第二第三的英文单词
    Dependency Walker
    刪除當前目錄隱藏文件,非隱藏文件,文件夾等好用的批處理。
    使用 Sandcastle Help File Builder 制作 VS.NET 的 HELP 文件
    字符“23.00”转成int型!Input string was not in a correct format.
    VisualStudio 2010 SP1安装时提示计算机环境导致无法安装的解决办法
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/7261260.html
Copyright © 2011-2022 走看看