codeforces 776E The Holmes Children

mac2022-06-30  148

目录

codeforces 776E The Holmes Children题意题解Code

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)\)如下:\[ F_k(n)=\begin{cases} f(g(n)) & k=1 \\ g(F_{k-1}(n)) & k>1且k\%mod=0 \\ f(F_{k-1}(n)) & k>1且k\%mod=1 \end{cases}\] 给出\(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+'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; }

转载于:https://www.cnblogs.com/Apocrypha/p/9537691.html

相关资源:垃圾分类数据集及代码
最新回复(0)