欧拉函数
\(O(\sqrt n)\)求单个\(\varphi(x)\)的值
上公式:
\[\varphi(n)=n\times \prod_{i=1}^s\frac{p_i-1}{p_i}
\]
- 引理:若\(p\)为质数,则\(\varphi(p^k)=p^k-p^{k-1}\)
因为与\(p^k\)不互质的只有\(p\)的倍数,而\(p^k\)中\(p\)的倍数有\(p^{k-1}\)个
由唯一分解定理,\(\varphi(x)\)函数的积性,以及引理可推:
\[\begin{aligned}
\varphi(n)&=n\times \prod_{i=1}^s(p_i^{k_i})\\
&=\prod_{i=1}^s(p_i-1)\times p_i^{k_i-1}\\
&=\prod_{i=1}^s{p_i^{k_i}\times(1-\frac{1}{p_i})}\\
&=n\prod_{i=1}^s(1-\frac{1}{p_i})
\end{aligned}
\]
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;
}
筛法求\(\varphi(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] 仪仗队
- 求队伍整齐时能看到的学生人数。
题解看这篇,因为好像只有他和我的结论一样
柿子不会推,但是听说挺板子的,大概:
\[\text{在第}i\text{行第}j\text{列的一个人能被看见当且仅当}\gcd(i,j)=1
\]
\[Ans=2\times\sum_{i=2}^{n-1}\varphi(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\),求 \(1\le x,y\le n\)且 \(\gcd(x,y)\)为素数的数对\((x,y)\)有多少对。
\[\begin{align}
\because
Ans&=\sum_{p\in{prime}}\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)=p]\\
\therefore
Ans &= \sum_{p\in{prime}}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(i,j)=1]
\\
&={\sum_{p\in{prime}}(\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}(2\times\sum_{j=1}^{i}[\gcd(i,j)=1])-1)}\\
&=\sum_{p\in{prime}}(2\times\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\varphi(i)-1)
\end{align}
\]
#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 的问题
- 求\(\sum_{i=1}^{N}\gcd(i,N)\)。
显然对于任意\(i \le n\),\(\gcd(i,n)\)一定是 \(n\) 的一个约数
\[\begin{aligned}
\sum_{i=1}^{n}\gcd(i,n)&=\sum_{d\mid n}d\times\sum_{i=1}^{n}[\gcd(i,n)=d] \\
&= \sum_{d\mid n}d\times\sum_{i=1}^{\frac{n}{d}}[\gcd(i,\frac{n}{d})=1]\\
&=\sum_{d\mid n}d\times \varphi(\frac{n}{d})
\end{aligned}
\]
#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;
}
前面的区域以后再买探索吧
欧拉定理
\[a^b\equiv a^{b\mod \varphi(m)}(\mod m)
\]
扩展欧拉定理
当\(a,m\in \mathbb Z\)时:
\[\begin{aligned}
a^b \equiv \begin{cases}
a^b, &b<\varphi(m)\\
a^{b \mod \varphi(m)+\varphi(m)},& b\ge\varphi(m)
\end{cases}
(\mod m)
\end{aligned}
\]
证明\(\Huge \to To\space be\space 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;
}

浙公网安备 33010602011771号