• [bzoj2242][SDOI2011]计算器


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    你被要求设计一个计算器完成以下三项任务:
    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)的最小非负整数。
    1<=y,z,p<=10^9

    第一问快速幂 第二问exgcd 第三问bsgs

    然后bsgs的时候感觉写$y^{ax-b}=z$比较舒服,这样$y^b$可以直接乘到右边

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define ll long long
    using namespace std;
    inline 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 n,k,y,z,p,MN;
    ll a,b;
    map<int,int> mp; 
    
    int pow(int x,int k,int mod)
    {
        if(mod==1) return 0;
        int sum=1;
        for(;k;k>>=1,x=1LL*x*x%mod)
            if(k&1) sum=1LL*sum*x%mod;
        return sum;
    } 
    
    int exgcd(int a,int b,ll&x,ll&y)
    {
        if(!b){x=1;y=0;return a;}
        int c=exgcd(b,a%b,x,y);
        ll t=x;x=y;y=t-(a/b)*x;
        return c;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            if(k==1)
            {
                for(int i=1;i<=n;i++)
                    y=read(),z=read(),p=read(),printf("%d
    ",pow(y,z,p));
            }
            if(k==2)
            {
                for(int i=1;i<=n;i++)
                {
                    y=read(),z=read(),p=read();
                    int c=exgcd(y,p,a,b);
                    if(z%c) puts("Orz, I cannot find x!");
                    else y/=c,z/=c,p/=c,printf("%lld
    ",((a*z/c)%p+p)%p);
                }
            }
            if(k==3)
            {
                for(int i=1;i<=n;i++)
                {
                    mp.clear();
                    y=read();z=read();p=read();y%=p;MN=ceil(sqrt(p));
                    if(!y&&!z)puts("1");else
                    if(!y)puts("Orz, I cannot find x!");
                    else if(p==1) puts("0");
                    else
                    {
                        int times=pow(y,MN,p);bool flag=0;
                        for(int j=0,k=z%p;j<=MN;j++,k=1LL*k*y%p)
                            mp[k]=j;
                        for(int j=1,k=times;j<MN;j++,k=1LL*k*times%p)
                            if(mp[k]) {flag=1,printf("%lld
    ",1LL*j*MN-mp[k]);break;}
                        if(!flag) puts("Orz, I cannot find x!");
                    }
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    如何通過編程獲取列表項目的附件以及多行文本中的文件內容
    小技巧:如何管理保存在本地的用户凭据
    WF 4.0中如何实现xaml工作流的动态加载
    使用jquery构造自己的多级菜单
    和安蕾尔的合影
    360太tmd脑残了
    3D 打印机技术设想
    再放2张数字油画
    解决问题的艺术:半小时编程实现照片的反转负冲特效
    承接数字油画图稿/线条图定制(出图)业务
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2242.html
Copyright © 2020-2023  润新知