codeforces 776E The Holmes Children
codeforces 776E The Holmes Children
题意
定义\(f(n)\)为满足\(x+y=n\)并且\(gcd(x,y)=1\)的有序正整数对个数,定义\(g(n)=\sum_{d|n}f(\frac{n}{d})\),定义\(F_k(n)\)如下:
给出\(n\),\(k\),求\(F_k(n)\)。\((1\leq n,k \leq 10^{12})\)
题解
首先观察\(f(n)\),可以比较容易地推出\(f(n)=\phi(n)\)。推导过程如下:我们先假设一对\((x,y)\),使得\(x+y=n\)并且\(gcd(x,y)=k\neq1\),于是我们可以推出\(gcd(x,n-x)=k\),\(k\)为\(x\)和\(n-x\)的一个因数,所以\(k\)也是\(n\)的一个因数,那么\(gcd(n,x)=k\),所以我们可以得知所有不满足条件的正整数对\((x,y)\)的\(x\)都不是与\(n\)互质的,所以满足条件的就是和\(n\)互质的那些,那么这个就是求欧拉函数了。
然后我们去看\(g(n)\),可以退出\(g(n)=n\),因为一个数所有因数的欧拉函数之和等于这个数本身。推导过程如下:假设\(n=a*b\),那么\(\phi(b)\)为所有与\(b\)的\(gcd\)为1的数,那么这些数与\(n\)的\(gcd\)为\(a\),所以所有与\(n\)的\(gcd\)为\(a\)的数都会对\(\phi(b)\)作出1的贡献,而由于每个小于\(n\)的数都与\(n\)有一个\(gcd\),所以每个数一定都会作出1的贡献,最后答案就是\(n\)。
知道这两个结论之后,就可以将\(F_k(n)\)变成\(\phi^{\frac{k+1}{2}}(n)\),即求\(\frac{k+1}{2}\)次的欧拉函数,而由于欧拉函数的值求到\(log\)次左右之后就会变成1,所以我们最多求\(log\)次欧拉函数,直到\(n=1\)的时候,就可以直接输出答案了,总的复杂度为\(O(logn*\sqrt{n})\)。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
#define PAUSE printf("Press Enter key to continue..."); fgetc(stdin);
const ll Md=1e9+7;
ll n,k;
/*==================Define Area================*/
ll Euler(ll x) {
ll res=x;
for(ll i=2ll;i*i<=x;i++) {
if(x%i==0) {
res=res-res/i;
while(x%i==0) x/=i;
}
}
if(x>1) res-=res/x;
return res;
}
void Calc() {
ll c=(k+1)/2;
ll res=Euler(n);
c--;
while(c--) {
res=Euler(res);
if(res==1) break;
}
printf("%lld\n",res%Md);
}
int main() {
read(n);read(k);
Calc();
return 0;
}