题目链接:C. Alternating Sum
题意:就是给出一个n+1长度周期为k的序列,求按照所给公式求和,输出答案。
思路:按周期求,先求出第一个周期 轻易可以推出,每个周期的和是一个等比数列,公比q为(b/a)^k,因为这些数字都比较大,等比数列求和公式a*(q^n-1)*(q-1)^-1;涉及到除法运算,需要用到逆元(逆元素是指一个可以取消另一给定元素运算的元素,在数学里,逆元素广义化了加法中的加法逆元和乘法中的倒数)就可以解决了。(q-1)^-1%mod=(q-1)^(mod-2)%mod。幂运算用快速幂。
代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const long long mod=1e9+9;
string s;
ll qpow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0)
{
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main()
{
ll n,a,b,k;
cin>>n>>a>>b>>k;
cin>>s;
ll res=0;
for(int i=0;i<s.size();++i)
{
int flag;
s[i]=='+'?flag=1:flag=-1;
res= ((res+flag*qpow(a, n-i, mod) * qpow(b, i, mod) )% mod + mod) % mod;
}
ll t = qpow(b, k, mod) * qpow(a, k * (mod - 2), mod) % mod;
if (t == 1)
{
res = res * ((n + 1) / k) % mod;
}
else
{
res = res * (qpow(t, (n+1)/k, mod) - 1) % mod * qpow(t-1, mod - 2, mod) % mod;
}
cout<<res;
return 0;
}