• 3283: 运算器


    3283: 运算器

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 340  Solved: 105
    [Submit][Status][Discuss]

    Description

    操作有3种:
     

    Input

    第一行一个正整数N,描述数据组数。
    接下来的N行,每行4个正整数Sum,y,z,p。
    Sum表述询问类型,如上题所述。对于第2种要求,若X不存在,则输出“Math Error”
     

    Output

     
    要求有N行输出,每行一个整数,为询问的答案。

    Sample Input

    4
    1 2 10 1000
    2 3 1 1000
    2 2 3 4
    3 2 7 9

    Sample Output

    24
    0
    Math Error
    3

    HINT

    操作1个数小于501。保证Y,Z,P小于10^9

    操作2个数小于51 保证Y,Z,P小于10^9 P不一定为质数

    操作3个数小于51 保证Y,Z小于10^9,P小于10^9

    P不一定为质数


    P<=10^9

    假设分解质因数后,P=p1^s1*p2^s2*……保证pi^ki<=10^5

    Source

    操作1:快速幂
    操作2:扩展BSGS
    操作3:扩展lucas
     
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    struct Thash{
        static const ll N=1e6+5,MOD=233333;
        ll tot,val[N],h[N],next[N],head[MOD+100];
        void clear(){tot=0;memset(head,0,sizeof head);}
        void insert(ll H,ll VAL){
            for(ll i=head[H%MOD];i;i=next[i]) if(h[i]==H){val[i]=VAL;return ;}
            h[++tot]=H;val[tot]=VAL;next[tot]=head[H%MOD];head[H%MOD]=tot;
        }
        ll get(ll H){
            for(ll i=head[H%MOD];i;i=next[i]) if(h[i]==H) return val[i];
            return -1;
        }
    }M;
    inline ll read(){
        ll 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;
    }
    ll fpow(ll a,ll p,ll mod){
        ll res=1;
        for(;p;p>>=1,a=a*a%mod) if(p&1) res=res*a%mod;
        return res;
    }
    ll gcd(ll a,ll b){
        if(!b) return a;
        return gcd(b,a%b);
    }
    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;
    }
    ll inv(ll a,ll p){
        ll d,x,y;
        exgcd(a,p,d,x,y);
        return d==1?(x%p+p)%p:-1;
    }
    ll BSGS(ll a,ll b,ll mod){
        M.clear();
        ll m=(ll)ceil(sqrt(mod+0.5));
        ll t=1;
        for(ll i=0;i<m;i++){
            M.insert(t,i);
            t=t*a%mod; 
        }
        ll base=inv(t,mod);
        ll res=b;
        for(ll i=0,z;i<m;i++){
            if((z=M.get(res))!=-1) return i*m+z;
            res=res*base%mod;
        }
        return -1;
    }
    ll solve(ll a,ll b,ll mod){
        ll A=1,D=1,cnt=0,ans;
        for(int i=0;i<=50;i++){
            if(A==b) return i;
            A=A*a%mod;
        }
        for(ll t;(t=gcd(a,mod))!=1;){
            if(b%t)return -1;
            b/=t;
            mod/=t;
            D*=a/t;D%=mod;
            cnt++;
        }
        b=b*inv(D,mod)%mod;
        ans=BSGS(a,b,mod);
        if(~ans) return ans+cnt;
        return -1;
    }
    ll mul(ll n,ll pi,ll pk){
        if(!n) return 1;
        ll ans=1;
        if(n/pk){
            for(ll i=2;i<=pk;i++) if(i%pi) ans=ans*i%pk;
            ans=fpow(ans,n/pk,pk);
        }
        for(ll i=2;i<=n%pk;i++) if(i%pi) ans=ans*i%pk;
        return ans*mul(n/pi,pi,pk)%pk;
    }
    ll C(ll n,ll m,ll pi,ll pk,ll mod){
        if(n<m) return 0;
        ll a=mul(n,pi,pk),b=mul(m,pi,pk),c=mul(n-m,pi,pk);
        ll ans,k(0);
        for(ll i=n;i;i/=pi) k+=i/pi;
        for(ll i=m;i;i/=pi) k-=i/pi;
        for(ll i=n-m;i;i/=pi) k-=i/pi;
        ans=a*inv(b,pk)%pk*inv(c,pk)%pk*fpow(pi,k,pk)%pk;
        return ans*(mod/pk)%mod*inv(mod/pk,pk)%mod;
    }
    void case2(ll a,ll b,ll c){
        ll ans=solve(a,b%c,c);
        if(~ans) printf("%lld
    ",ans);
        else puts("Math Error");
    }
    void case3(ll n,ll m,ll MOD){
        ll x=MOD,ans=0;
        for(ll pk,i=2;i*i<=MOD;i++){
            if(!(x%i)){
                pk=1;
                while(!(x%i)) pk*=i,x/=i;
                ans=(ans+C(n,m,i,pk,MOD))%MOD;
            }
        }
        if(x>1) ans=(ans+C(n,m,x,x,MOD))%MOD;
        printf("%lld
    ",ans);
    }
    int main(){
        int T=read();
        for(ll opt,y,z,p;T--;){
            opt=read();y=read();z=read();p=read();
            if(opt==1) printf("%lld
    ",fpow(y,z,p));
            if(opt==2) case2(y,z,p);
            if(opt==3) case3(z,y,p);
        }
        return 0;
    }
  • 相关阅读:
    linux清理内存
    华为代码注释标准
    Spring缓存机制的理解
    jQuery实现动态分割div—通过拖动分隔栏实现上下、左右动态改变左右、上下两个相邻div的大小
    模仿iframe框架,由分隔栏动态改变左右两侧div大小———基于jQuery
    js实现由分隔栏决定两侧div的大小—js动态分割div
    java基于socket的简单聊天系统
    中国移动归属地区号大全
    将本地光盘做成yum源
    windows下设置计划任务自动执行PHP脚本
  • 原文地址:https://www.cnblogs.com/shenben/p/6600886.html
Copyright © 2020-2023  润新知