码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 776E The Holmes Children

时间:2018-08-26 18:37:31      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:int   void   utc   euler   efi   tin   return   href   ase   

目录

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%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;
}

codeforces 776E The Holmes Children

标签:int   void   utc   euler   efi   tin   return   href   ase   

原文地址:https://www.cnblogs.com/Apocrypha/p/9537691.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!