这题做起来感觉挺坑的。。。大概是不习惯这种数学题吧,也可能是这次前两题太简单了?
anyway,首先如果暴力去算每一个数的值肯定是tle的,注意到这是以k为周期的,那么我们其实可以先算出前k个数的和,然后对于后面的数,每k个一组,每组的和都是上一组的和*(a^k/b^k),这里要求一波乘法逆元。1e9+9是质数所以费马小定理搞一下就行。然后这些和怎么加呢?如果一个个去加也是会tle的…所以就祭出等比数列求和公式吧…注意特判公比为1的情况就行。。。还有就是中间要注意各种数值为负的问题,负数取模似乎会出现很多玄学问题?
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
const long long mod=1e9+9;
typedef long long ll;
ll pow(ll x,ll n,ll mod)//快速幂
{
ll ans=1;
x%=mod;
while(n){
if(n&1)
ans=ans*x%mod;
x=x*x%mod;
n>>=1;
}
return ans;
}
int main()
{
ll n,a,b,k;
string str;
cin>>n>>a>>b>>k;
cin>>str;
int i,j;
long long fh[100005];//记录符号
for(i=0;i<str.size();i++){
if(str[i]=='+')
fh[i]=1ll;
else
fh[i]=-1;
}
ll ans=0;
for(i=0;i<k;i++){
ans=(ans+fh[i]*pow(a,n-i,mod)*pow(b,i,mod)%mod)%mod;
ans = (ans + mod) % mod;//这句不能少!保证ans为正!
}//求前k个
ll temp=ans;
ll ak=pow(a,k,mod),bk=pow(b,k,mod);//求a^k,b^k
ll akn=pow(ak,mod-2,mod);//a^n的乘法逆元,费马小定理
ll t=akn*bk%mod;
if(t==1)//特判公比为1
cout<<temp*((n+1)/k)%mod<<endl;
else{
ans=temp*(pow(t,(n+1)/k,mod)-1)%mod*(pow(t-1,mod-2,mod))%mod;//等比数列求和
cout<<ans<<endl;
}
return 0;
}