NYOJ1197 你会加吗?
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1197
题意:要你求一个等比数列前N项和, q, N都小于10^18, 输出的结果对666666求余。
这道题明显一看就知道要用快速幂, 我们知道等比数列的前n项和公式, 但是我们是要对求出的结果求余, 所以我们就不能用前n项的和。我们可以发现
n为偶数:n&1==0,n=2k,S=A+A^2….A^k + A^k(A+A^2….A^k );
n为奇数:n&1==1,n=2k+1,S=A+A^2….A^k +A^(k+1)+ A^(k+1)(A+A^2….A^k )
所以我们可以进行二分递归求和。这样我要计算的就很少了。
-
#include<stdio.h>
-
#include<string.h>
-
#include<algorithm>
-
using
namespace
std;
-
#define LL long long
-
const LL mod =
666666;
-
LL pow_mod(LL a, LL n)//快速幂
-
{
-
LL ans =
1, temp = a;
-
while(n >
0)
-
{
-
if(n&
1)
-
ans = (ans * temp) % mod;
-
temp = (temp * temp) % mod;
-
n /=
2;
-
}
-
return ans;
-
}
-
LL sum(LL a, LL k)//二分递归求和
-
{
-
if(k ==
0)
-
return
1;
-
if(k ==
1)
-
return a;
-
LL ans =
1;
-
LL as = sum(a, k/
2);
-
if(k &
1)
-
{
-
LL t = pow_mod(a, k/
2+
1);
-
ans = (as + t + (t*as)%mod) % mod;
-
}
-
else
-
{
-
LL t = pow_mod(a, k/
2);
-
ans = (as + ((t*as)%mod)) % mod;
-
}
-
return ans;
-
}
-
int main()
-
{
-
LL a, n;
-
while(~
scanf(
"%lld%lld", &a, &n))
-
{
-
printf(
"%lld\n", sum(a%mod, n));
//注意a要求余之后传进去, 不然相乘可能就超数据类型了
-
}
-
return
0;
-
}