思路:
首先打表,会发现这道题是一个循环节问题,每一个周期会构成一个等比数列,然后特判一下公比是否为1即可,若公比为1,ans = q * m(周期数);否则,利用等比数列的前n项求和公式求出ans即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const ll N=1e5+10;
ll n,a ,b,k;
char s[N];
ll qmi(ll a,ll b){
ll ans=1;
while(b){
if(b & 1){
ans = ans * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return ans;
}
ll inv(ll x){
return qmi(x,mod-2);
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&a,&b,&k);
scanf("%s",s);
ll m = (n + 1)/k; //循环节的个数
ll a1 = 0,t1,t2,tmp,ans;
for(ll i = 0;i < k;i ++){
t1 = qmi(a,n-i);
t2 = qmi(b,i);
a1 += (s[i]=='-'?-1:1) * t1 * t2 % mod;
a1 = (a1 + mod) % mod;
}
//a1 表示第一个循环结的值,即等比数列的第一项
ans = a1;
ll q = qmi(b,k);
q = q * qmi(inv(a),k)%mod;
// q 表示 公比
if(q==1){
ans = a1 * m % mod; // 如果公比为1的话直接让第一个循环节的值 * 循环节的个数
}else{ // 如果公比不为一的话
ans = a1;
ans=ans * (qmi(q,m)-1) % mod;
ans=ans * inv(q-1) % mod;
// ans 为等比数列前n项的和
}
printf("%lld\n",ans);
}