牛客算法題目-歐拉函數的運用

題目描述 

小a和小b來到了一條佈滿了黃金的街道上。它們想要帶幾塊黃金回去,然而這裏的城管擔心他們拿走的太多,於是要求小a和小b通過做一個遊戲來決定最後得到的黃金的數量。
遊戲規則是這樣的:
假設道路長度爲n米(左端點爲0,右端點爲n),同時給出一個數k(下面會提到k的用法)
設小a初始時的黃金數量爲A,小b初始時的黃金數量爲B
小a從1出發走向n−1,小b從n−1出發走向1,兩人的速度均爲1m/s
假設某一時刻(必須爲整數)小a的位置爲x,小b的位置爲y,若gcd(n,x)=1且gcd(n,y)=1,那麼小a的黃金數量A會變爲A∗kx(kg),小b的黃金數量B會變爲B∗ky(kg)
當小a到達n−1時遊戲結束
小a想知道在遊戲結束時A+B的值
答案對109+7取模

輸入描述:

一行四個整數n,k,A,B

輸出描述:

輸出一個整數表示答案

示例1

輸入

複製

4 2 1 1

輸出

複製

32

說明


 

示例2

輸入

複製

5 1 1 1

輸出

複製

2

備註:


 

保證3⩽n⩽10^8,1⩽A,B,k⩽10^13

 

題解:

AC代碼:

套用歐拉函數模板和快速冪模板AC

#include<bits/stdc++.h>
using namespace std;
const long long m = 1e9 + 7;
#define LL long long
LL euler(LL n)
{
	LL ans = n;
	for (LL i = 2; i*i <= n; ++i) {
		if (n%i == 0) {
			ans -= ans / i;
			while (n%i == 0) {
				n /= i;
			}
		}
	}
	if (n > 1)ans -= ans / n;
	return ans;
}
int fun(LL a, LL b, LL c)
{
	LL res, t;
	res = 1; //res記錄最後的模,初始化爲1 
	t = a % c;//t代表a^n,初始化爲a%c; 
	while (b)//當b不爲0時 
	{
		if (b & 1)//如果b的二進制的最後一位是1,代表a^t存在 
		{
			res = res * t%c;//更新最後的模 
		}
		t = t * t%c;//t=a^n*a^n,向前走一位,例如a^8=a^4*a^4 
		b >>= 1;//b的二進制向右移動一位,去掉最後一位 
	}
	return res;
}
int main()
{
	LL n, k, a, b;
	cin >> n >> k >> a >> b;
	LL ans = 1;
	LL x = euler(n)*n / 2;
	LL t = k % m;
	ans = fun(t, x, m);
	cout << (a + b)*ans%m << endl;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章