• 一本通 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;
    }
    
  • 相关阅读:
    今天英语有何新收获?
    今天了解了解了外包这一行业
    今天英语有何新收获?
    sicp 练习1.7
    今天英语有何新收获
    今天英语有何新收获?
    反射(初尝)
    初学正则表达式
    sicp 练习1.8 【有点疑惑】
    [tip]Windows filename MAX_PATH limitation
  • 原文地址:https://www.cnblogs.com/wangjunrui/p/11923429.html
Copyright © 2020-2023  润新知