欧拉函数

欧拉函数

O(n)求单个φ(x)的值

上公式:

φ(n)=n×i=1spi1pi

  • 引理:若p为质数,则φ(pk)=pkpk1
    因为与pk不互质的只有p的倍数,而pkp的倍数有pk1

由唯一分解定理,φ(x)函数的积性,以及引理可推:

φ(n)=n×i=1s(piki)=i=1s(pi1)×piki1=i=1spiki×(11pi)=ni=1s(11pi)

il int phi(int x)
{
	int m=sqrt(x+0.5),re=x;
	for(int i=2;i<=m;i++)
    	if(x%i==0) 
	{
    	     re=re/i*(i-1);
    	     while(x%i==0)x/=i;
   	}
	if(x>1) re=re/x*(x-1);
	return re;
}

筛法求φ(n)

il void Euler()
{
	phi[1]=1,isprime[1]=isprime[0]=1;
	for(ri int i(2);i<=N-3;++i)
	{
		if(!isprime[i]) prime[++cnt]=i,phi[i]=i-1;
		for(ri int j(1);j<=cnt&&prime[j]*i<N;++j)
		{
			isprime[prime[j]*i]=true;
			if(i%prime[j]) phi[prime[j]*i]=phi[prime[j]]*phi[i];
			else {phi[prime[j]*i]=prime[j]*phi[i];break;}
		}
	}
//	for(ri int i(1);i<=N-3;++i) printf("%d ",phi[i]);
}

T1 P2158 [SDOI2008] 仪仗队

  • 求队伍整齐时能看到的学生人数。

题解看这篇因为好像只有他和我的结论一样
柿子不会推,但是听说挺板子的,大概:

在第i行第j列的一个人能被看见当且仅当gcd(i,j)=1

Ans=2×i=2n1φ(i)+3

#include<cstdio>
#include<iostream>
#include<algorithm>
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
const int N=4e4+2;
int n,phi[N],prime[N],cnt,ans=3;
bool isprime[N];
il void pre()
{
    isprime[1]=true,phi[1]=1;
    for(ri int i=2;i<n;++i)
    {
        if(!isprime[i]) prime[++cnt]=i,phi[i]=i-1;
        ans+=phi[i]*2;
        for(ri int j=1;j<=cnt&&i*prime[j]<=n;++j)
        {
            isprime[i*prime[j]]=true;
            if(i%prime[j]) phi[i*prime[j]]=phi[i]*phi[prime[j]]; //n与pi互质
            else {phi[i*prime[j]]=phi[i]*prime[j];break;} //n'包含了n的所有质因子
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    if(n==1) return printf("0"),0; 
	pre(),cout<<ans;
    return 0;
}

T2 P2568 GCD

  • 给定正整数n,求 1x,yngcd(x,y)为素数的数对(x,y)有多少对。

参考

(1)Ans=pprimei=1nj=1n[gcd(i,j)=p](2)Ans=pprimei=1npj=1np[gcd(i,j)=1](3)=pprime(i=1np(2×j=1i[gcd(i,j)=1])1)(4)=pprime(2×i=1npφ(i)1)

#include<cstdio>
#include<iostream>
#include<algorithm>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
//#define int long long
using namespace std;
cs int N=1e7+3;
int n,prime[664582],cnt,phi[N];
long long ans,sp[N];
bool isprime[N];
il void Euler()
{
	sp[1]=phi[1]=1,isprime[1]=isprime[0]=1;
	for(ri int i(2);i<=n;++i)
	{
		if(!isprime[i]) prime[++cnt]=i,phi[i]=i-1;
		for(ri int j(1);j<=cnt&&prime[j]*i<N;++j)
		{
			isprime[prime[j]*i]=true;
			if(i%prime[j]) phi[prime[j]*i]=phi[prime[j]]*phi[i];
			else {phi[prime[j]*i]=prime[j]*phi[i];break;}
		}
		sp[i]=sp[i-1]+phi[i];
	}
//	for(ri int i(1);i<=100;++i) printf("%d ",phi[i]);pc('\n');
//	for(ri int i(1);i<=100;++i) printf("%d ",sp[i]);
}
signed main()
{
	freopen("gcd.in","r",stdin);
	freopen("gcd.out","w",stdout);
	scanf("%d",&n),Euler();
	for(ri int p(1);p<=cnt;++p)
		ans+=1ll*2*sp[n/prime[p]]-1;
	printf("%lld",ans);
	return 0;
}

T3 [SDOI2012] Longge 的问题

  • i=1Ngcd(i,N)

参考

显然对于任意ingcd(i,n)一定是 n 的一个约数

i=1ngcd(i,n)=dnd×i=1n[gcd(i,n)=d]=dnd×i=1nd[gcd(i,nd)=1]=dnd×φ(nd)

#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
int n,ans=0; 
il void read(int &as)
{
	int f=1;char ch=getchar();as=0;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
il int phi(int n) {
  int ans=n;
  for(int i=2;i*i<=n;i++)
    if(n%i==0)
	{
      ans=ans/i*(i-1);
      while(n%i==0) n/=i;
    }
  if (n>1) ans=ans/n*(n-1);
  return ans;
}
il int solve(int x)
{
	int re=0,i;
	for(i=1;i*i<x;++i)
		if(x%i==0) re+=i*phi(x/i)+(x/i)*phi(i);
	if(i*i==x) re+=i*phi(i);
	return re;
 } 
signed main()
{
	read(n),wt(solve(n));
	return 0;
}
前面的区域以后再买探索吧

欧拉定理

ababmodφ(m)(modm)

扩展欧拉定理

a,mZ时:

ab{ab,b<φ(m)abmodφ(m)+φ(m),bφ(m)(modm)

证明To be continued

T1 【模板】扩展欧拉定理

#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
int a,Mod,b,p;
bool flag=0;
il void read(int &as)
{
	as=0;char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		as=(as<<3)+(as<<1)+(ch^48),ch=getchar();
		if(as>=p) as%=p,flag=1;
	}
	as+=(flag?p:0);
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il int phi(int x)
{
	int m=sqrt(x+0.5),re=x;
	for(int i=2;i<=m;i++)
    	if(x%i==0) 
		{
    		re=re/i*(i-1);
    		while(x%i==0)x/=i;
   		}
	if(x>1) re=re/x*(x-1);
	return re;
}
il int qpow(int base,int power)
{
	int re=1;
	while(power>0)
	{
		if(power&1) (re*=base)%=Mod;
		power>>=1,(base*=base)%=Mod;
	}
	return re%Mod;
}
signed main()
{
	scanf("%lld%lld",&a,&Mod);
	p=phi(Mod),read(b),wt(qpow(a,b));
	return 0;
}
posted @   Bertidurlah  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示