首页 > 代码库 > 3283: 运算器

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

giant step baby step

操作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\n",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\n",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\n",fpow(y,z,p));        if(opt==2) case2(y,z,p);        if(opt==3) case3(z,y,p);    }    return 0;}

 

3283: 运算器