NYOJ1197 你会加吗?

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 ) 

所以我们可以进行二分递归求和。这样我要计算的就很少了。


  
  
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. using namespace std;
  5. #define LL long long
  6. const LL mod = 666666;
  7. LL pow_mod(LL a, LL n)//快速幂
  8. {
  9. LL ans = 1, temp = a;
  10. while(n > 0)
  11. {
  12. if(n& 1)
  13. ans = (ans * temp) % mod;
  14. temp = (temp * temp) % mod;
  15. n /= 2;
  16. }
  17. return ans;
  18. }
  19. LL sum(LL a, LL k)//二分递归求和
  20. {
  21. if(k == 0)
  22. return 1;
  23. if(k == 1)
  24. return a;
  25. LL ans = 1;
  26. LL as = sum(a, k/ 2);
  27. if(k & 1)
  28. {
  29. LL t = pow_mod(a, k/ 2+ 1);
  30. ans = (as + t + (t*as)%mod) % mod;
  31. }
  32. else
  33. {
  34. LL t = pow_mod(a, k/ 2);
  35. ans = (as + ((t*as)%mod)) % mod;
  36. }
  37. return ans;
  38. }
  39. int main()
  40. {
  41. LL a, n;
  42. while(~ scanf( "%lld%lld", &a, &n))
  43. {
  44. printf( "%lld\n", sum(a%mod, n)); //注意a要求余之后传进去, 不然相乘可能就超数据类型了
  45. }
  46. return 0;
  47. }




猜你喜欢

转载自blog.csdn.net/shf1730797676/article/details/82149976