一本通 P1806 计算器

Posted wangjunrui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一本通 P1806 计算器相关的知识,希望对你有一定的参考价值。

一本通原题

事实上这题是快速幂+扩展Lucus定理+扩展BSGS的题。
事实上,只要做出这三道模板题就可以做出来了

【模板】快速幂||取余运算

【模板】exBSGS/Spoj3105 Mod

【模板】扩展卢卡斯

#include<cstdio>
#include<cctype>
#include<cmath>
#include<map>
#define re register
#define ll long long
using namespace std;
namespace IO
{
    const int SIZE=1<<25;
    char ibuf[SIZE],*iS,*iT;
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    template<typename T>
    inline void read(T & x)
    {
        x=0;
        bool b=false;
        char ch=gc();
        while(!isdigit(ch)&&ch^'-')
            ch=gc();
        if(ch=='-')
        {
            b=true;
            ch=gc();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^'0');
            ch=gc();
        }
        if(b)
            x=~x+1;
        return;
    }
#undef gc
    char Out[1<<30],*fe=Out,ch[25];
    int num=0;
    template<typename T>
    inline void write(T x)
    {
        if(!x)
            *fe++='0';
        if(x<0)
        {
            *fe++='-';
            x=-x;
        }
        while(x)
        {
            ch[++num]=x%10+'0';
            x/=10;
        }
        while(num)
            *fe++=ch[num--];
        *fe++='
';
    }
    inline void write_str(char *s)
    {
        for(re int i=0; s[i]; i++)
            *fe++=s[i];
        *fe++='
';
    }
    inline void flush()
    {
        fwrite(Out,1,fe-Out,stdout);
        fe=Out;
    }
}
using namespace IO;
namespace quick
{
    template<typename T1,typename T2,typename T3>
    inline T1 quickpow(T1 a,T2 b,T3 n)
    {
        T1 res=1;
        while(b)
        {
            if(b&1)
                res=res*a%n;
            a=a*a%n;
            b>>=1;
        }
        return res;
    }
}
namespace Exlucus
{
    inline void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
    {
        if(!b)
        {
            d=a;
            x=1;
            y=0;
            return;
        }
        exgcd(b,a%b,d,y,x);
        y-=a/b*x;
        return;
    }
    inline ll fac(ll n,ll pi,ll pk)
    {
        if(!n)
            return 1ll;
        ll res=1ll;
        for(re int i=2; i<=pk; ++i)
            if(i%pi)
                res=res*i%pk;
        res=quick::quickpow(res,n/pk,pk);
        for(re int i=2; i<=n%pk; ++i)
            if(i%pi)
                res=res*i%pk;
        return res*fac(n/pi,pi,pk)%pk;
    }
    inline ll inv(ll n,ll mod)
    {
        ll x,y,d;
        exgcd(n,mod,d,x,y);
        return (x%mod+mod)%mod;
    }
    inline ll CRT(ll b,ll mod,ll p)
    {
        return b*inv(p/mod,mod)%p*(p/mod)%p;
    }
    inline ll C(ll n,ll m,ll pi,ll pk)
    {
        ll up=fac(n,pi,pk),d1=fac(m,pi,pk),d2=fac(n-m,pi,pk),k=0;
        for(re ll i=n; i; i/=pi)
            k+=i/pi;
        for(re ll i=m; i; i/=pi)
            k-=i/pi;
        for(re ll i=n-m; i; i/=pi)
            k-=i/pi;
        return up*inv(d1,pk)%pk*inv(d2,pk)%pk*quick::quickpow(pi,k,pk)%pk;
    }
    inline ll exlucus(ll n,ll m,ll p)
    {
        ll res=0,tmp=p,pk;
        int lim=sqrt(p)+5;
        for(re int i=2; i<=lim; ++i)
            if(tmp%i==0)
            {
                pk=1;
                while(tmp%i==0)
                {
                    pk*=i;
                    tmp/=i;
                }
                res=(res+CRT(C(n,m,i,pk),pk,p))%p;
            }
        if(tmp>1)
            res=(res+CRT(C(n,m,tmp,tmp),tmp,p))%p;
        return res;
    }
}
namespace ExBSGS
{
#define mul(a,b,p) (1ll*a*b%p)
    template<typename T>
    inline T gcd(T a,T b)
    {
        return b?gcd(b,a%b):a;
    }
    map<ll,ll>Hash;
    inline ll exBSGS(ll a,ll b,ll p)
    {
        a%=p;
        b%=p;
        if(b==1)
            return 0;
        if(!b&&!a)
            return 1;
        if(!a)
            return -1;
        if(!b)
        {
            ll res=0,d;
            while((d=gcd(a,p))!=1)
            {
                ++res;
                p/=d;
                if(p==1)
                    return res;
            }
            return -1;
        }
        ll res=0,A=a,B=b,P=p,C=1,d;
        while((d=gcd(A,P))!=1)
        {
            if(B%d)
                return -1;
            P/=d;
            B/=d;
            C=mul(C,A/d,P);
            ++res;
            if(C==B)
                return res;
        }
        Hash.clear();
        ll f=1,t=sqrt(P)+1;
        for(re int i=0; i<t; ++i)
        {
            Hash[mul(f,B,P)]=i;
            f=mul(f,A,P);
        }
        int tf=f;
        f=mul(f,C,P);
        for(re int i=1; i<=t; ++i)
        {
            if(Hash.find(f)!=Hash.end())
                return res+i*t-Hash[f];
            f=mul(f,tf,P);
        }
        return -1;
    }
#undef mul
}
using namespace Exlucus;
using namespace quick;
using namespace ExBSGS;
int main()
{
    re ll y,z,p,T;
    int type;
    for(read(T); T; T--)
    {
        IO::read(type);
        IO::read(y);
        IO::read(z);
        IO::read(p);
        if(type==1)
            IO::write(quick::quickpow(y,z,p));
        else if(type==3)
            IO::write(Exlucus::exlucus(z,y,p));
        else if(type==2)
        {
            ll ans=ExBSGS::exBSGS(y,z,p);
            if(~ans)
                IO::write(ans);
            else
                IO::write_str("Math Error");
        }
    }
    IO::flush();
    return 0;
}

以上是关于一本通 P1806 计算器的主要内容,如果未能解决你的问题,请参考以下文章

信息奥赛一本通 1060:均值

《信息学奥赛一本通》题库 1034 计算三角形面积——基础

一本通1157 哥德巴赫猜想

一本通1166 求f(x,n)

「一本通 1.2 练习 3」灯泡(三分/公式法)(三角函数,计算几何)

一本通网站基础篇完结纪念