[2020.12.07周一]赛氪A题

赛氪

题解:根据欧几里得辗转相除,很容易想到\(gcd(i,n-i)=gcd(i,n)\)

\[\begin{align*} &当n>1,f(n)=\sum_{i=1}^{n-1}[gcd(i,n-i)==1]=\sum_{i=1}^{n-1}[gcd(i,n)==1]+[gcd(n,n)==0]=\sum_{i=1}^{n}[gcd(i,n)==1]=\varphi (n)\\ &\therefore f(n)=\varphi(n)\\ &g(n)=\sum_{d|n}f(\frac{n}{d})=\sum_{d|n}f(\frac{n}{d})·1(d)=\varphi*1=id,恒等函数\\ &\therefore g(n)=n\\ &综上,这题只要作(k+1)/2次欧拉就好了;\\ &但这个k依然很大,但没关系因为log次必然迭代到1,按照cy的说法是暴跳到1然后break;\\ &复杂度O(n\log n)\\ &下面来证明[思路by cy]:log次必然迭代到1(赛场上因为没证出来,不敢冲)\\ &根据欧拉定理,n=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n},\varphi(n)=n·\prod_{i=1}^{s} \frac{p_i-1}{p_i}\\ &\varphi(奇数)=偶数\\ &\varphi(偶数)\le偶数/2\\ &\varphi(n)\le n-1\\ &因此,\varphi(\varphi(n))\le n/2 &p.s.这个证明不严谨,因为欧拉函数没有单调性,cy想了一个办法规避它,但我还没看懂 \end{align*} \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
long long  euler(long long  n)
{
    long long res=n,a=n;
    for(long long i=2;i*i<=a;i++){
        if(a%i==0){
            res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;//返回euler(n)
}
int main()
{
    int  T;ll n, k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&k);
        k=(k+1)/2;
        for(int i=1;i<=k;i++){
            n=euler(n);
            if(n==1) break;
        }
        printf("%lld\n",n%mod);
    }
}
posted @ 2020-12-09 15:49  zx0710  阅读(137)  评论(0编辑  收藏  举报