链接:https://ac.nowcoder.com/acm/contest/317/D
来源:牛客网
时间限制: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的位置为x,小b的位置为y,若gcd(n,x)=1且gcd(n,y)=1,那么小a的黄金数量A会变为A∗k^x(kg),小b的黄金数量B会变为B∗k^y(kg)
当小a到达n−1时游戏结束
小a想知道在游戏结束时A+B的值
答案对 1e9+7 取模
输入描述:
一行四个整数 n,k,A,B
输出描述:
输出一个整数表示答案
示例1
输入
4 2 1 1
输出
32
说明
初始时A=1,B=1
第一个时刻如图所示,小a在1,小b在3,满足条件,此时A=1∗2^1=2, B=1∗2^3=8
第二个时刻小a在2,小b在2,不满足条件
第三个时刻小a在3,小b在1,满足条件,此时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⩽n⩽10^8, 1⩽A,B,k⩽10^13
题意:就是求A*k^x1*k^x2.....*k^xn..+B*k^y1*k^y2.......*k^yn = A*k^(x1+x2+...xn)+B*k^(y1+y2+...yn); 要求是: gcd(n,x)=1,gcd(n,y)=1;并且到达x,y位置的时间一样,最后要模1e9+7
题解:如果gcd(n,x)=1则gcd(n,n-x)=1这就保证了时间一样,而且这样找下来就是与n互质的所有数,而且这样的话,(x1+x2+...+xn)=(y1+y2+...yn)=与n互质的所有数的和,这样我们就可以想到,用欧拉函数,求所有与n互质的和;
和为sum=n*get_euler(n)/2; 这样就变成求(A*k^sum+B*k^sum)%mod;更多解释看代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll get_euler(ll n){ // 欧拉函数模板
ll res=n,a=n;
for (ll i = 2; i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a=a/i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
ll quick(ll a,ll b,ll c){//快速幂
ll ans=1;
a=a%c;
while(b!=0){
if(b&1) ans=(ans*a)%c;
b>>=1;
a=(a*a)%c;
}
return ans;
}
int main(){
ll n,k,a,b;
scanf("%lld%lld%lld%lld",&n,&k,&a,&b);
ll sum=n*get_euler(n)/2;
a=a*quick(k,sum,mod)%mod;//quick()用来求k^sum
b=b*quick(k,sum,mod)%mod;
printf("%lld\n",(a+b)%mod);
return 0;
}