牛客 小a与黄金街道(欧拉函数)

欧拉函数

唯一分解定理:n=p_1^{a_1}*p_2^{a_2}*p_3^{a_3}*......*p_m^{a_m}

欧拉函数:\phi (n)=n*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*......*(1-\frac{1}{p_m})     (1~n中与n互质的数的个数)

\phi (1)=1

欧拉函数常用性质:

  1. 如果n, m互质,则 \phi (nm)=\phi (n) \phi(m)
  2. 小于等于n,且与n互质的数的和是 \phi (n) *n/2
  3. 欧拉定理:若n,a为正整数,且n,a互质,则:a^{\phi (n)}\equiv 1(mod\ n)

下面的题中用到了第二条性质。


链接:https://ac.nowcoder.com/acm/problem/22145
来源:牛客网

小a与黄金街道

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

小a和小b来到了一条布满了黄金的街道上。它们想要带几块黄金回去,然而这里的城管担心他们拿走的太多,于是要求小a和小b通过做一个游戏来决定最后得到的黄金的数量。
游戏规则是这样的:
假设道路长度为n米(左端点为0,右端点为n),同时给出一个数k(下面会提到k的用法)
设小a初始时的黄金数量为A,小b初始时的黄金数量为B
小a从1出发走向n - 1,小b从n - 1出发走向1,两人的速度均为1m/s
假设某一时刻(必须为整数)小a的位置为xx,小b的位置为yy,若gcd(n,x) = 1且gcd(n,y) = 1,那么小a的黄金数量A会变为A * k^x(kg),小b的黄金数量B会变为B * k^y(kg)
当小a到达n - 1n−1时游戏结束
小a想知道在游戏结束时A+B的值
答案对10^9 + 7取模

输入描述:

一行四个整数n,k, A, Bn,k,A,B

输出描述:

输出一个整数表示答案

示例1

输入

4 2 1 1

输出

32

说明

初始时A = 1, B = 1

第一个时刻如图所示,小a在11,小b在33,满足条件,此时A = 1 * 2^1 = 2, B = 1 * 2^3 = 8

第二个时刻小a在22,小b在22,不满足条件

第三个时刻小a在33,小b在11,满足条件,此时 A = 2 * 2^3 = 16, B = 8 * 2^1 = 16

此时游戏结束A = 2 * 2^3 = 16, B = 8 * 2^1 = 16

A + B = 32

示例2

输入

5 1 1 1

输出

2

备注:

保证 3 \leqslant n \leqslant 10^{8} , 1 \leqslant A, B, k \leqslant 10^{13}


分析:

可以看出最后A和B是相等的,每到一个符合要求的点都会乘 (k^x),最后会得到:

A*k^{x_1+x_2+...+x_i}+B*k^{x_1+x_2+...+x_i}=(A+B)*k^{x_1+x_2+...+x_i}

其中所有的x都与n互质,那么这就符合上面的第二条性质,就可以算出所有x的和,在这之前首先要算出欧拉值\phi (n),求欧拉值就可以用 O(\sqrt{n}) 的复杂度得到。

 Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll qpow(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
            res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res % mod;
}
int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    ll n, k, A, B;
    cin >> n >> k >> A >> B;
    ll e = n, nn = n; //e是欧拉函数值φ(n)
    for (ll p = 2; p * p <= n; p++) //求φ(n)
        if (n % p == 0)
        {
            e = e / p * (p - 1); //(1-1/pi)=(pi-1)/p
            while (n % p == 0)
                n /= p;
        }
    if (n > 1)
        e = e / n * (n - 1);
    e = e * nn / 2; //1~n中所有与n互质的数的和=φ(n)*n/2
    cout << (A + B) * qpow(k, e) % mod << endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值