NYOJ1197 你会加吗?

来源:互联网 发布:linux oracle ora00119 编辑:程序博客网 时间:2024/06/16 16:56

题目链接: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 longconst 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;}




0 0
原创粉丝点击