模板-数论/计数

1、快速幂/龟速乘

inline ll qpow(ll a,ll b,ll p){ll ans=1%p;for(;b;b>>=1){if(b&1) ans=ans*a%p;a=a*a%p;}return ans;}
inline ll mul(ll a,ll b,ll p){ll ans=0;for(;b;b>>=1){if(b&1) ans=(ans+a)%p;a=(a<<1)%p;}return ans;}

2、块速幂

ll qpow(ll a,ll b){ll ans=1%p;for(;b;b>>=1){if(b&1) ans=ans*a%p;a=a*a%p;}return ans;}
ll pw[2][N];
inline void init()
{
	pw[0][0]=pw[1][0]=1; 
	for(int i=1;i<=M;i++) pw[0][i]=pw[0][i-1]*x%p;
	x2=pw[0][M];
	for(int i=1;i<=M;i++) pw[1][i]=pw[1][i-1]*x2%p;
}
//in main
pw[1][a/M]*pw[0][a%M]%p

3、GCD/LCM

int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return (a||b)?(ll)a/gcd(a,b)*b:0;}

4、exGCD

ll exgcd(ll a,ll b,ll& x,ll& y)
{
	if(!b){x=1,y=0; return a;}
	ll d=exgcd(b,a%b,x,y);
	ll z=x;x=y,y=z-y*(a/b);
	return d;
}

5、单个数乘法逆元

inline ll inv(x){return qpow(x,p-2);}//p为质数
inline int inv(int i){int x,y; int d=exgcd(i,p,x,y); return (x%p+p)%p;}//p为任意数

6、乘法逆元线性递推

inv[1]=1;
for(int i=2;i<=n;i++)
{
	inv[i]=(ll)(p-p/i)*inv[p%i]%p;
}

7、线性筛

inline void Euler_Sieve(int n)
{
	for(int i=2;i<=n;i++)
	{
		if(!nsp[i]) nsp[i]=primes[++t]=i;
		for(int j=1;j<=t && primes[j]<=n/i;j++)
		{
			nsp[i*primes[j]]=primes[j];
			if(primes[j]>=nsp[i]) break;
		}
	}
}

8、中国剩余定理 (CRT)

inline ll CRT()
{
	ll M=1,ans=0;
	for(int i=1;i<=n;i++) M*=m[i];
	for(int i=1;i<=n;i++)
	{
		ll Mi=M/m[i],x,y;
		exgcd(Mi,m[i],x,y);
		x=(x%m[i]+m[i])%m[i];//Mi*x=1 (mod m[i])
		ans+=a[i]*Mi*x;
	}
	return ans%M;
}

9、扩展中国剩余定理 (exCRT)

inline ll exCRT()
{
	//x=a1 (mod m1)
	ll m1=a[1],a1=b[1];
	for(int i=2;i<=n;i++)
	{
		ll m2=a[i],a2=b[i],p1,p2;
		//m1*p1-m2*p2=a2-a1
		ll c=((a2-a1)%m2+m2)%m2;
		ll d=exgcd(m1,m2,p1,p2);
		if(c%d!=0) return -1;
		m2/=d;
		p1=(mul(p1,c/d,m2)+m2)%m2;//p1=((c/d)*p1%m2+m2)%m2;
		//x=a (mod m) <= a=m1*p1+a1,m=lcm(m1,m2)
		a1+=m1*p1, m1*=m2, a1=(a1%m1+m1)%m1;
	}
	return a1;
}

10、扩展欧拉定理

ll read_h()
{
	ll n=0; char ch;
	for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
	for(;'0'<=ch&&ch<='9';ch=getchar())
	{
		n=((n<<3)+(n<<1)+(ch^48));
		if(n>=pm) n%=pm,flag=true;
	}
	return n;
}

ll phi(ll x)
{
	ll ans=x;
	for(ll i=2;i*i<=x;i++)
		if(x%i==0)
		{
			ans=ans/i*(i-1);
			for(;x%i==0;x/=i);
		}
	if(x>1) ans=ans/x*(x-1);
	return ans;
}

inline ll expow(ll a,ll b,ll m)
{
	ll ans=qpow(a,b,m);
	if(flag) ans=ans*qpow(a,pm,m)%m;
	return ans;
}
//in main
a=read(),m=read();
pm=phi(m);
b=read_h();
printf("%lld\n",expow(a,b,m));
posted @ 2021-11-12 17:55  Coinred  阅读(47)  评论(0)    收藏  举报