等比数列求和
题目
已知
a
i
=
a
1
×
q
i
−
1
a_{i}=a_{1}×q^{i-1}
ai=a1×qi−1,求
s
u
m
i
=
1
n
a
i
sum_{i=1}^{n}a_{i}
sumi=1nai
结果可能很大,请对987654323取模
输入
第一行一个正整数t,表示数据组数
接下来t行,每行三个整数 n , a 1 , q n,a_{1},q n,a1,q 。
( 0 < n , a 1 , q < 1 0 9 , 0 < t < 10000 ) (0<n,a_{1},q<10^{9},0<t<10000) (0<n,a1,q<109,0<t<10000)
输出
t 行,每行输出一个整数,表示等比数列的和 mod 987654323 的值。
输入样例
2
3 2 7
3 2 1
输出样例
114
6
思路
这里只给分治做法。
设等比数列和为 S S S
当n为偶数的时候 S n = S n / 2 + a n / 2 + 1 × S n / 2 S_{n}=S_{n/2}+a_{n/2+1}×S_{n/2} Sn=Sn/2+an/2+1×Sn/2
当n为奇数的时候 S n = S n / 2 + a n / 2 + 1 × S n / 2 + a n S_{n}=S_{n/2}+a_{n/2+1}×S_{n/2}+a_{n} Sn=Sn/2+an/2+1×Sn/2+an
结合快速幂,总体复杂度为 l o g n logn logn
代码
- 分治
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mod = 987654323;
ll qpow(ll a, ll n)
{
ll x = a, res = 1;
while (n > 0)
{
if (n & 1) res = (res*x) % mod;
x = (x*x) % mod;
n >>= 1;
}
return res % mod;
}
ll f(ll q, ll n)
{
if (n == 1) return 1;
ll tmp = f(q, n / 2);
tmp = (tmp + tmp * qpow(q, n / 2)) % mod;
if (n & 1)
{
return (tmp + qpow(q, n - 1)) % mod;
}
return tmp;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll a, n, q;
int t;
cin >> t;
while (t--)
{
cin >> n >> a >> q;
cout << (a*f(q, n)) % mod << "\n";
}
return 0;
}
#include <iostream>
using namespace std;
const int MOD=987654323;
unsigned long long sum(unsigned long long n,unsigned long long k)
{
n%=MOD;
unsigned long long ans=0;
unsigned long long power=n;
unsigned long long powersum=n;//S(y)
unsigned long long mul=1;//a^x
while (k)
{
if (k&1)
{
ans+=mul*powersum;
ans%=MOD;
mul*=power;
mul%=MOD;
}
powersum*=(power+1);
powersum%=MOD;
power*=power;
power%=MOD;
k>>=1;
}
return ans;
}
int main()
{
int T;
cin>>T;
while(T--){
unsigned long long n,k,a;
cin>>k>>a>>n;
cout<<(((sum(n,k-1)+1%MOD)%MOD)*(a%MOD))%MOD<<endl;
}
return 0;
}