问题描述:
样例:
实现解释:
这里等比数列求和使用到的知识点包括:分治和快速幂
其中分治的方法和快速幂的方法是从博客中学习到的:
等比数列分治求和:https://blog.csdn.net/qq_35937273/article/details/82750298
快速幂方法:https://www.cnblogs.com/lca1826/p/6748372.html
结合到本题目中可参考完整代码。
在分治求和和快速幂之外取模操作的实现解释如下:
根据描述可知最后的值是很大的,所以需要取余,但实际上在计算的过程中就需要进行取余操作了。所以需要对快速幂函数和分治函数进行一下处理:
首先操作的基础公式(取余的等价式):
(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p + p) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
a ^ b % p = ((a % p)^b) % p (4)
基于(4)首先需要对快速幂的乘数进行取模处理,然后在乘起来每一个值之前还需要对result进行取模处理,然后还需要对乘起来的值进行取模。这样才能保证快速幂得到的值得到了正常的取模处理(之前就是这里出错所以测试点只过了一个)
基于(1)和(3)需要对分治求和的返回结果分别进行取模处理。
坑点:
取余出现负数:数据超出了范围,是没正确取余导致的,因为正数取余不会得到负数。
完整代码:
#include<iostream> using namespace std; long long MOD = 987654323; long long quickPow(long long q,long long cnt) { long long mq = q%MOD; long long result = 1; while(cnt!=0) { if(cnt&1!=0) { result*=mq; result%=MOD; } mq*=mq; mq%=MOD; // if(cnt&1!=0) // { // result*=mq; // } // mq*=mq; cnt>>=1; } return result%MOD; } long long getSum(long long q,long long cnt) { if(cnt == 0) return 1; if(cnt&1!=0)//奇数 { long long coef = 1+quickPow(q,(cnt+1)/2); return ((coef%MOD)*getSum(q,(cnt-1)/2))%MOD; } else//偶数 { long long coef = 1+quickPow(q,cnt/2); return ((((coef%MOD)*getSum(q,cnt/2-1))%MOD)+quickPow(q,cnt))%MOD; } } int main() { long long cnt; cin >> cnt; long long n,a,q; while(cnt--) { cin >> n >> a >> q; cout << ((a%MOD)*getSum(q,n-1))%MOD << endl; } return 0; }
原文地址:https://www.cnblogs.com/doUlikewyx/p/11701182.html
时间: 2024-10-09 18:39:50