你们要的欧拉欧拉欧拉欧拉终于来了

欧拉函数

MITE:欧拉欧拉欧拉欧拉(beta)

我们用 φ(n)来表示欧拉函数
它等于<=n的数中与n互质的数的数目(1姑且认为与任何数互质吧)

首先当然是大家都擅长的暴力了,我们知道,两个数互质就是gcd=1,所以就有

int phi(int n)
{
   int ans=0;
   for(int i=1;i<=n;i++)
   	if(gcd(i,n)==1)
   		ans++;
   return n;
}

但是很多时候暴力是出不了奇迹的,所以我们需要更好的方法

很多时候我们思考问题要学会逆向思维,只要把不与n互质的数去掉的话剩下的不就是与n互质的了。还记得之前说过的定理吗,在讲线筛的时候,任何合数都能拆成n个素数的乘积。所以只要把小于n的n的所有素因数的倍数去掉就好啦,是不是很简单哇。具体做法就算简单容斥啦(此时,我终于想起了没有做容斥的博客,但是问题不大)

比如说24,它的素因数有2,3
小于等于24&&2的倍数:24/2=12
小于等于24&&3的倍数:24/3=8
2和3的倍数24/(2 * 3)
需要去除的数为24 *(1/2-1/6+1/3)
φ(24)=24(1-1/2-1/3+1/6)=24(1-1/2)(1-1/3)=8

再比如三个素数的2*3*5=30
φ(30)=30(1-1/2)(1-1/3)(1-1/5)=8

至于为什么具体转到容斥定理(还没写)

于是我们就可以有新的写法了

int phi(int n)
{
	int ans=n;
	for(int i=2;i*i<=n;i++)
	{
		//由于任何一个合数都至少有一个不大于根号n的素因子,所以只需遍历到根号n即可
		if(n%i==0)
		{
			ans = ans/i*(i-1);
			//防溢出
			while(n%i==0)n/=i;
			//使n的因子没有素数i的倍数
		}
	}
	if(n>1)
		ans=ans/n*(n-1);
	//如果n最终是素数的话会跳出循环,没有计算,所以这里还要再判断一次
	return ans;
}

聪明的同学们可能已经发现了,这东西是可以打表的
遍历一遍,只要遍历到素数的话它的所有倍数(包括它本身)都除以它乘它-1既/i*(i-1)

int phi[N];
void Euler()
{
	phi[1]=1;
	for(int i=2;i<N;i++)
	{
		if(phi[i])
		{
			for(int j=i;j<N;j+=i)
			{
				if(!phi[j]) phi[j]=j;
				phi[j]=phi[j]/i*(i-1);
			}
		}
	}
}

复杂度和埃筛差不多,O(nlnln n)

然后提一下欧拉函数的一些性质
1.若p为质数,φ ( p)=p-1

因为小于质数p的数都与p互质

2.若i mod p = 0,且p为质数,则φ( i * p ) = φ(i) *p

ϕ(i)=i(11a)(11p)\phi(i)=i*(1-\frac{1}{a})*(1-\frac{1}{p})

ϕ(ip)=ip(11a)(11p)=ϕ(i)p\phi(i*p)=i*p*(1-\frac{1}{a})*(1-\frac{1}{p})=\phi(i)*p

3.若i mod p ≠0,且p为质数, 那么 φ( i * p )=φ(i) * ( p-1 )

ϕ(i)=i(11a)(11b)\phi(i)=i*(1-\frac{1}{a})*(1-\frac{1}{b})

ϕ(ip)=ip(11a)(11b)(11p)=i(11a)(11b)(p1)=ϕ(i)(p1)\phi(i*p)=i*p*(1-\frac{1}{a})*(1-\frac{1}{b})*(1-\frac{1}{p})=i*(1-\frac{1}{a})*(1-\frac{1}{b})*(p-1)=\phi(i)*(p-1)

4.对于n=p^k ,有 ϕ(n)=(p1)pk1\phi(n)=(p-1) * p^{k-1}

ϕ(n)=ϕ(pk1p)=ϕ(pk1)p=...=ϕ(p)pk1=(p1)pk1\phi(n)=\phi(p^{k-1}*p)=\phi(p^{k-1})*p=...=\phi(p)*p^{k-1}=(p-1)*p^{k-1}

5.若gcd(n,m)=1,ϕ(nm)=ϕ(n)ϕ(m)\phi(n * m)=\phi(n) * \phi(m)

n与m互质,质数互不相同

6.n=pikin=\prod p_i^{k_i} ,则有ϕ(n)=n(11pi)\phi(n)=n * \prod (1-\frac{1}{p_i})

p为质数,易得(真的易得吖)

7.若gcd(a,m)=1,则aϕ(m)1a^{\phi(m)} \equiv 1 (mod m)

欧拉定理,下有证明

8.小于n且与n互质的数的和 S=n*ϕ(n)2\frac{\phi(n)}{2};

易知,若i与n互质,则n-i与n也互质

若i与n不互质 gcd(i,n)=a > 0, (n-i)/a=n/a-i/a为整数,故a也为n-i的因数,故 gcd(n,n-i) != 1

所以有S = n*ϕ(n)2\frac{\phi(n)}{2}

    i=dnϕ(d)\ \ \ \ \sum_{i=d|n}{\phi(d)}=n

ϕ(n)=dnμ(d)nd\phi(n)=\sum_{d|n}\mu(d)*\frac{n}{d}

由性质1 2 3 可得一种更快得筛法

const int N = 1e6+10;
int phi[N],prime[N];
int tot;
void Euler()
{
	phi[1] = 1;
	for(int i = 2; i < N;i++)
	{
		if(!phi[i])
		{
			phi[i]=i-1;
			prime[tot++];
		}
		for(int j=0;j<tot&&1ll*i*prime[j]<N;j++)
		{
			if(i%prime[j])
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			else
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
		}
	}
}

原理和线筛差不多就不多累赘了

欧拉定理

当a,m互质时,aϕ(m)1(mod m)a^{\phi(m)}\equiv1 (mod\ m)

枚举小于m与m互质的数x1,x2,...,xϕ(m)x_1,x_2,...,x_{\phi(m)}

pi=axip_i=a*x_i

则对于 i!=j,pi mod m != pj mod mi!=j ,有 p_i \ mod \ m \ != \ p_j \ mod \ m

$ p_i-p_j=a(x_i-x_j)$

因为a与m互质,xix_i与m互质,所以a(xixj)a(x_i-x_j)与m互质

(pipj)mod m!=0(p_i-p_j)mod\ m !=0

所以有pi mod m != pj mod mp_i \ mod \ m \ != \ p_j \ mod \ m

因此,对于确定的i,有确定的j使pimod&ThinSpace;&ThinSpace; m=xjp_i \mod\ m = x_j

且i对j是一一映射的

因此得i=1ϕ(m)pii=1ϕ(m)axiaϕ(m)i=1nxii=1nxi(mod m)\prod_{i=1}^{\phi(m)}p_i\equiv\prod_{i=1}^{\phi(m)}a*x_i\equiv a^{\phi(m)}*\prod_{i=1}^{n}x_i\equiv \prod_{i=1}^{n}x_i (mod\ m)

得证aϕ(m)1(mod m)a^{\phi(m)}\equiv 1(mod\ m)

拓展欧拉定理

ac{ac mod ϕ(m)           , gcd(a,m)=1ac                         , gcd(a,m)!=1,c&lt;ϕ(m)ac mod ϕ(m)+ϕ(m)   , gcd(a,m)!=1,c&gt;ϕ(m)     (mod m)a^c \equiv\begin{cases} a^{c \ mod\ \phi(m)} \ \ \ \ \ \ \ \ \ \ \ ,\ gcd(a,m)=1\\ a^c\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ,\ gcd(a,m)!=1,c&lt;\phi(m)\\ a^{c\ mod\ \phi(m)+\phi(m)}\ \ \ ,\ gcd(a,m)!=1,c&gt;\phi(m)\end{cases} \ \ \ \ \ (mod\ m)

证明有缘的话会给出来的(咕咕咕)

看了这个后就不要再写出ac(a mod p)c mod pa^c \equiv (a\ mod\ p)^{c\ mod\ p}(mod m)这种东西来了,这个是错的错的错的

欧拉降幂

就是当指数爆炸(超64位整数,几百位甚至更多)时可以用拓展欧拉定理来处理c mod ϕ(m)\phi(m)

int main()
{
	ll a,c,p;
	char b[100000];
	cin>>a>>b>>p;
	int l = strlen(b);
	for(int i=0;i<l;i++)
		c=(c*10+b[i]-'0')%p;
	cout<<qpow(a,c%phi(p)+phi(p),p)<<endl;
	return 0;
}

相关文章: