欧拉函数
互质:
互质是公约数只有1的两个整数,叫做互质整数。公约数只有1的两个自然数,叫做互质自然数,后者是前者的特殊情形
- 5和5不互质,因为5和5的公因数有1、5。
- 1和任何数都成倍数关系,但和任何数都互质。因为1的因数只有1,而互质数的原则是:只要两数的公因数只有1时,就说两数是互质数。因为1只有一个因数所以1既不是质数(素数),也不是合数,无法再找到1和其他数的别的公因数了。1和-1与所有整数互素,而且它们是唯一与0互素的整数。
- 互质数的写法:如c与m互质,则写作 ( c , m ) = 1 (c,m)=1 (c,m)=1
欧拉函数介绍:
- 在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1)。
- 此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。
- 从欧拉函数引伸出来在环论方面的事实和拉格朗日定理构成了欧拉定理的证明。
公式1:
φ
(
x
)
=
x
∏
i
=
1
n
(
1
−
1
p
i
)
(
其
中
p
1
,
p
2
…
…
p
n
为
x
的
所
有
质
因
数
,
x
是
不
为
0
的
整
数
)
\begin{aligned}\varphi \left( x\right) =x\prod ^{n}_{i=1}\left( 1-\dfrac{1}{p_{i}}\right) \\ \left(其中p_{1}, p_{2}……p_{n}为x的所有质因数,x是不为0的整数 \right) \end{aligned}
φ(x)=xi=1∏n(1−pi1)(其中p1,p2……pn为x的所有质因数,x是不为0的整数)
公式2:
φ
(
n
)
=
n
−
1
(
n
为
质
数
)
\begin{aligned}\varphi \left( n\right) =n-1\\ \left( n为质数\right) \end{aligned}
φ(n)=n−1(n为质数)
//常规求法
ll eular(ll n){
ll ans = n;
for(ll i=2; i<=sqrt(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;
}
//记忆化求法
void euler(){
for(int i=2;i<maxn;i++){
if(!Eu[i])
for(int j=i;j<maxn;j+=i){
if(!Eu[j])Eu[j]=j;
Eu[j]=Eu[j]/i*(i-1);
}
}
}
例题:
GCD(HDU-2588)
题意:
求 x < = n x <= n x<=n且 g c d ( x , n ) > = m gcd(x,n)>= m gcd(x,n)>=m 的 x x x的个数
思路:
gcd
(
x
,
N
)
≥
M
⇔
gcd
(
x
M
,
N
M
)
≥
1
\gcd \left( x,N\right) \geq M\Leftrightarrow \gcd \left( \dfrac{x}{M},\dfrac{N}{M}\right) \geq 1
gcd(x,N)≥M⇔gcd(Mx,MN)≥1
gcd
(
x
M
,
N
M
)
≥
1
⇔
gcd
(
x
α
,
N
α
)
=
1
(
α
M
≥
1
,
α
没
必
要
是
M
的
倍
数
)
\begin{aligned}\gcd \left( \dfrac{x}{M},\dfrac{N}{M}\right) \geq 1\Leftrightarrow \gcd \left( \dfrac{x}{\alpha },\dfrac{N}{\alpha }\right) =1\\ \left( \dfrac{\alpha }{M}\geq 1,\alpha没必要是M的倍数\right) \end{aligned}
gcd(Mx,MN)≥1⇔gcd(αx,αN)=1(Mα≥1,α没必要是M的倍数)
先找出所有满足条件的
α
\alpha
α(首先是n的因数,然后比m大)值,之后利用欧拉函数,求出
x
α
\dfrac{x}{\alpha}
αx的个数,最后累加个数即可
代码:
#include<iostream>
#include<stdio.h>
#include<cmath>
#define ll long long
using namespace std;
ll eular(ll n){
ll ans = n;
int g=(int)sqrt(n+0.5);
for(ll i=2; i<=g; 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;
}
int main(){
int t;
scanf("%d",&t);
ll n,m;
while(t--){
scanf("%lld%lld",&n,&m);
ll ans=0;
for(ll i=1;i*i<=n;i++){
if(n%i==0){//找出满足条件的α(i)值
if(i>=m) ans+=eular(n/i);
if(i*i!=n&&n/i>=m) ans+=eular(i);
}
}
printf("%lld\n",ans);
}
}
中国剩余定理
解如下方程:
(
S
)
:
{
x
≡
a
1
(
m
o
d
m
1
)
x
≡
a
2
(
m
o
d
m
2
)
⋮
x
≡
a
n
(
m
o
d
m
n
)
\left( S\right) :\begin{cases}x\equiv a_{1}\left( modm_{1}\right) \\ x\equiv a_{2}\left( modm_{2}\right) \\ \vdots \\ x\equiv a_{n}\left( modm_{n}\right) \end{cases}
(S):⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡a1(modm1)x≡a2(modm2)⋮x≡an(modmn)
先取
M
=
∏
i
=
1
n
m
i
M=\prod ^{n}_{i=1}m_{i}
M=∏i=1nmi ,
M
i
=
M
m
i
M_{i}=\dfrac{M}{m_{i}}
Mi=miM
之后令 t i = M i − 1 t_{i}=M_{i}^{-1} ti=Mi−1为 M i M_{i} Mi模 m i m_{i} mi的数论倒数( t i t_{i} ti为 M i M_{i} Mi模 m i m_{i} mi意义下的逆元)
那么方程组
(
S
)
(S)
(S)的通解形式为
x
=
a
1
t
1
M
1
+
a
2
t
2
M
2
+
…
+
a
n
t
n
M
n
+
k
M
=
k
M
+
∑
i
=
1
n
a
i
t
i
M
i
,
k
∈
Z
\begin{aligned}x=a_{1}t_{1}M_{1}+a_{2}t_{2}M_{2}+\ldots +a_{n}t_{n}M_{n}+kM\\ =kM+\sum ^{n}_{i=1}a_{i}t_{i}M_{i},k\in Z\end{aligned}
x=a1t1M1+a2t2M2+…+antnMn+kM=kM+i=1∑naitiMi,k∈Z
在模
M
M
M意义下,方程组
(
S
)
(S)
(S)只有一个解:
x
=
(
∑
i
=
1
n
a
i
t
i
M
i
)
m
o
d
M
x=\left( \sum ^{n}_{i=1}a_{i}t_{i}M_{i}\right) modM
x=(i=1∑naitiMi)modM
例题:
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll;
int a[15],b[15];
ll m=1,ans=0,p,q;
void exgcd1(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1,y=0;return ;}
exgcd1(b,a%b,y,x);
y-=x*(a/b);
}//无返回值版
ll exgcd2(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1, y=0; return a;}
int gc=exgcd2(b,a%b,y,x);
y-=a/b*x;
return gc;
}//递归求ax+by=gcd(a,b),有返回值版
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]),m*=a[i];
for(int i=1;i<=n;i++)
{
ll x=m/a[i];
exgcd1(x,a[i],p,q);
p=(p%a[i]+a[i])%a[i];//p的最小正整数解
ans+=((p*b[i]*x)%m+m)%m;
ans%=m;
}
printf("%lld",ans);
return 0;
}