请思考以下问题:
任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?
(比如,在1到8之中,有多少个数与8构成互质关系?)
计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。
特别的,φ(1)=1(和1互质的数(小于等于1)就是1本身)。
对于一个正整数N的素数幂分解N=P1q1P2q2…Pnqn,其中,Pi为素数(1≤i≤n)。
根据第二条性质得到:
φ(N)=φ(P1q1P2q2…Pnqn)=φ(P1q)φ(P2q2)…φ(Pnqn)
注意:每种质因数只有一个。
若n是质数p的k次幂,φ(n)=pk-pk-1=(p-1)pk-1,因为除了p的倍数外,其他数都跟n互质。
简单证明:φ(n)=pk-pk-1=(p-1)pk-1
证明:
由φ(n)的定义值,φ(pk)等于从pk减去在1,…,pk中与p不互素的数的个数。因为p是素数,故φ(pk)等于从pk减去在1,…,pk中被p整除的数的个数。而在
1,…,p,p+1,…,2p,…,pa-1 * p
中,易知p的倍数共有pa-1个,即得φ(n)=pk-pk-1=(p-1)pk-1
利用欧拉函数和它本身不同质因数的关系,用筛法计算出某个范围内所有数的欧拉函数值。
欧拉函数和它本身不同质因数的关系:
欧拉函数: φ(N)=N{∏p|N}(1-1/p)
亦即:
φ ( N ) = N ∗ ∏ ( 1 − 1 / p ) ( P 是 数 N 的 质 因 数 ) φ(N)=N* ∏(1-1/p)(P是数N的质因数)
φ(N)=N∗∏(1−1/p)(P是数N的质因数),如:
φ(10)=10×(1-1/2)×(1-1/5)=4; 10的质因数为2,5;
φ(30)=30×(1-1/2)×(1-1/3)×(1-1/5)=8; 30的质因数为2,3,5;
φ(49)=49×(1-1/7)=42。 49的质因数为7。
设n≥1,则有∑φ(n)=n,其中d|n,d>0.
输入样例:
2
7 5
10 2
输出样例:
1
4
思路: f(n)函数就是欧拉函数的定义,并且g(n)函数就是欧拉函数扩展的定理应用,因此只需要进行计算即可
素数筛核心代码:
void pri(ll N){
for(int i=2;i<=N;i++){
if(!vis[i]){
p[++tot]=i;
vis[i]=1;
}
for(int j=1;j<=tot&&i*p[j]<=N;j++){
vis[i*p[j]]=1;
if(i%p[j]==0){
break;
}
}
}
}
代码:
#include
using namespace std;
typedef long long int ll;
const ll maxn=1e5+10;
const ll maxm=1e8+10;
const ll mod=1e9+7;
ll n,k;
ll p[maxn];
ll vis[maxn];
ll tot;
void pri(ll N){
for(int i=2;i<=N;i++){
if(!vis[i]){
p[++tot]=i;
vis[i]=1;
}
for(int j=1;j<=tot&&i*p[j]<=N;j++){
vis[i*p[j]]=1;
if(i%p[j]==0){
break;
}
}
}
}
ll ppi(ll x){
ll ans=x;
for(int i=1;i<=tot;i++){
if(x%p[i]){
continue;
}
ans=ans/p[i]*(p[i]-1);
while(x%p[i]==0){
x/=p[i];
}
}
if(x>1){
ans=ans/x*(x-1);
}
return ans;
}
int main(){
pri(maxn-1);
ll t;
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&k);
k=(k+1)/2;
for(int i=1;i<=k&&n>1;i++){
n=ppi(n);
}
printf("%lld\n",n%mod);
}
return 0;
}