参考资料 : 欧拉函数及欧拉线性筛 - 辞树 - 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 eq 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
",ans+(f?0:1));
}
return 0;
}