[数论] 欧拉函数
参考资料 : 欧拉函数及欧拉线性筛 - 辞树 - CSDN博客
欧拉(Eular)函数 $\varphi $
欧拉函数是小于n的正整数中与n互质的数的数目(\(\varphi(1)=1\))
(互质:两数有且仅有公因数 $ 1 $)
$ $
$ $
欧拉函数 \(\varphi\) 的性质
1. 若\(n\)为质数,\(\varphi(n) = n-1\)
2. 对于 \(n = p^{k}\) ,有 \(\varphi(n) = (p-1)* p^{k-1}\)
3. 欧拉函数是积性函数,若\(gcd(n,m)=1\),即\(n\),\(m\)互质,有\(\varphi(n*m) = \varphi(n)*\varphi(m)\)
4. \(n = \sum_{i=1} ^{m} p_{i} ^{q_{i}}\) ,则\(\varphi (n) = n * \prod _{i=1} ^{m} (i - \frac{1}{p_{i}})\)
5. 欧拉定理:对于互质的\(a\)和\(m\),\(a^{\varphi(m)} \equiv 1 (mod\) \(m)\)
6.小于\(n\)且与\(n\)互质的数的和:\(S = \frac {n * \varphi(n)}{2}\)
7. 对于质数\(p\),若\(n\) \(mod\) \(p=0\),则\(\varphi(n*p) = \varphi(n) * p\) ;若\(n\) \(mod\) \(p\neq 0\),则 \(\varphi(n*p) = \varphi(n) *(p-1)\)
8. 若\(\sum_{d|n}\varphi(d) = n\),则 \(\varphi(n) = \sum_{d|n} \mu(d) * \frac{n}{d}\)
显然后面几条我们用不上....反正先写着咯
于是有了欧拉筛求素数顺便(雾)求欧拉函数值的代码
void getprime(int lim)
{
nop[1]=1,phi[1]=0;
for(int i=2;i<=lim;i++)
{
if(!nop[i])pri[++size]=i,phi[i]=i-1;
for(int j=1;j<=size&&i*pri[j]<=lim;j++)
{
nop[i*pri[j]]=1;
if(i%pri[j]==0)
{
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
else phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
}
说说几道题吧
题面:
艾莉欧在她的被子上发现了一个数字 N ,她觉得只要找出最小的 \(x\) 使得\(\varphi^{x}(N) =1\)
。根据这个 $x $她就能找到曾经绑架她的外星人的线索了。当然,她是不会去
算,请你帮助她算出最小的 \(x\)。
输入:
第一行一个正整数$ test$,接下来 $test$ 组数据每组数据第一行一个正整数$ m $,接下来
$m $行每行两个正整数 $q_{i} $ 和 \(p_{i}\)
其中$\prod_{i=1}^{m}p_{i}^{q_{i}}$为 $N$ 的标准分解形式。
1
2
2 2
3 1
输出:
每行一个整数$ans$
3
样例解释:
\(N=12 , \varphi(12)=4,\varphi(4)=2,\varphi(2)=1\),所以答案是3.
\(\varphi(\prod_{i=1}^{m}p_{i}^{q_{i}})=\prod_{i=1}^{m}(p_{i}-1)p_{i}^{q_{i}-1}\)
分析:
其实题目求的是使得$\varphi( \varphi... (\varphi (N)))=1$中$\varphi$操作的个数
通过打表 可以发现,只有\(\varphi(1)\)和\(\varphi(2)\)的值为1,所以在最后一步前必然要把\(N\)转化为2(因为不能转为1啊,转1就两种方式),那么根据题目所提示之公式,因为每次出现了 \(q_{i}-1\),则必然会变少一个因子2(幂数变小),求出2的个数即可。但要注意若刚开始没有因子2则要多一步
phi[i]表示i含有几个2,即要几次变成1
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+6;
int phi[N],prime[N];
bool isprime[N];
int T,m,p,q,cnt;
void Prime(){
memset(prime,0,sizeof(prime));
memset(isprime,false,sizeof(isprime));
isprime[0]=isprime[1]=true;
phi[1]=1;
for(int i=1;i<=N;++i){
if(!isprime[i]){
prime[++cnt]=i;
phi[i]=phi[i-1];
}
for(int j=1;j<=cnt&&prime[j]*i<=N;++j){
isprime[prime[j]*i]=true;
phi[i*prime[j]]=phi[i]+phi[prime[j]];
if(!(i%prime[j])) break;
}
}
}
int main(){
freopen("alien.in","r",stdin);
freopen("alien.out","w",stdout);
Prime();
scanf("%d",&T);
while(T--){
int ans=0;
bool f=false;
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&p,&q);
if(p==2)f=true;
ans+=phi[p]*q;
}
printf("%d\n",ans+(f?0:1));
}
return 0;
}