Alternating Sum

216 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

传送门 请添加图片描述

思路:

首先可以得出这是一个公比为b/a的等比数列,它的周期为k,因而每两个相邻周期的和的关系为sumi=sumi1(b/a)ksum_i=sum_{i-1}*(b/a)^{k},所以我们可以先求出第一个周期的和,剩下的就是一个等比数列求和即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll mod = 1e9+9;
ll qpow(ll a,ll b)
{
	ll ans = 1;
	while(b)
	{
		if(b&1)ans = ans*a%mod;
		b>>=1;
		a = a*a%mod;
	}
	return ans;
}

void Solve()
{
	ll n,a,b,k;
	cin>>n>>a>>b>>k;
	string s;
	cin>>s;
	ll ans = 0;
	ll sum1 = 0;
	if(a==1 && b==1)
	{
		for(int i = 0; i < k; i++)
		{
			if(s[i] == '+')ans++;
			else ans--;
		}
		ans*=(n+1)/k;
		while(ans<0)ans+=mod;
		cout<<ans%mod<<endl;
		return;
	}
	for(int i = 0; i < k; i++)
	{
		if(s[i] == '+')
		sum1+=qpow(a,n-i)*qpow(b,i)%mod;
		else
		sum1=(sum1-qpow(a,n-i)*qpow(b,i)+mod)%mod;
		sum1%=mod;
	}
	ll q = qpow(b,k)*qpow(qpow(a,k),mod-2)%mod;
	if(q == 1)
	{
		cout<<sum1*(n+1)/k%mod<<endl;
		return ;
	}
	ans = sum1*(qpow(q,(n+1)/k)-1)%mod*qpow(q-1,mod-2)%mod;
	while(ans<0)ans+=mod;
	cout<<ans%mod<<endl;
}

int main()
{
	Solve();
}