Codeforces Round #400 E. The Holmes Children (欧拉)

13 篇文章 1 订阅
3 篇文章 0 订阅

Description

The Holmes children are fighting over who amongst them is the cleverest.

Mycroft asked Sherlock and Eurus to find value of f(n), where f(1) = 1 and for n ≥ 2, f(n) is the number of distinct ordered positive integer pairs (x, y) that satisfy x + y = n and gcd(x, y) = 1. The integer gcd(a, b) is the greatest common divisor of a and b.

Sherlock said that solving this was child’s play and asked Mycroft to instead get the value of g(n)=Σndf(n/d) . Summation is done over all positive integers d that divide n.

Eurus was quietly observing all this and finally came up with her problem to astonish both Sherlock and Mycroft.

She defined a k-composite function Fk(n) recursively as follows:

Fk(n)=f(g(n)),g(Fk1(n)),f(Fk1(n)),for k = 1,for k>1 and k mod 2 = 0,for k>1 and k mod 2 = 1.

She wants them to tell the value of Fk(n) modulo 1000000007.

Input

A single line of input contains two space separated integers n ( 1n1012 ) and k ( 1k1012 ) indicating that Eurus asks Sherlock and Mycroft to find the value of Fk(n) modulo 1000000007.

Output

Output a single integer — the value of Fk(n) modulo 1000000007.

题意

数论题,不过多解释题意。就是根据公式以及 f(n), g(n) 的定义求 Fk(n)

分析

貌似所有与超大数据范围有关,同时又包括了对素数描述的题目,最后都是用 欧拉公式 求解的。:approve:膜拜。

首先分析 f(n) f(1)=1 , f(n) 为满足 x+y=n gcd(x,y)==1 的二元组 (x, y) 的组数。

上述使得 gcd(x, y)==1 与使得 gcd(x,n)==1 等价(非严格证明):

假设存在 gcd(x, y)==1gcd(x, n)!=1

那么显然 gcd(x, n)==k , k 为非 1 的正整数。同时可认为 n=k×b , x=k×a ,且 a, b 均为正整数, a<b

 x+y=n ,  y=nx=k×(ba)

显然,x 与 y 至少有一个公约数 k ,即 gcd(x, y)=1 不成立,与假设矛盾。

f(n) 为与 [1, n) 中与 n 互质的数的个数,此题还是逃不过 欧拉

​再看 g(n) g(n)=Σdnf(n/d) ,无论是找规律还是公式求解,都可以很快得出 g(n)=n 成立 :haha: 。

所以最终公式就可以被化简为:

Fk(n)=ff...f(k+12fn)

可以想象,由于欧拉的快速坍缩,故时间复杂度可行。

HINT: 当在某次操作后答案已经变成 1 。直接跳出循环(否则 k 太大,会超时。)

代码

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
long long eular(long long n){
    long long ans = n;
    int sqt = sqrt(n + 0.5);
    for(int i = 2;i<=sqt;i++){
        if(n % i == 0){
            ans -= ans/i;
            while(n % i == 0)   n /= i;
        }
    }
    if(n > 1)   ans -= ans/n;
    return ans;
}
int main()
{
    long long n, k;
    scanf("%I64d %I64d",&n,&k);
    for(int i=1;i<=k && n!=1;i+=2)
        n = eular(n);
    printf("%d\n",n%mod);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值