题意:告诉你前k个的符号+1,-1 。 对于 i>=k的符号=i-k;
思路:
1.对于前k个符号,每个符号对应后面的数列都是一个等比数列 q > 1。
2.for循环一遍前k个符号,等比公式。
3.问题在于,解决这个等比数列如果不取模就涉及浮点数。因此正确做法使用逆元,逆元在数论中很重要,解决了在取模情况下的分数问题。
有逆元学习需要的,有学长的博客推荐 逆元学习 写得非常好。
用快速幂求逆元时 inva=qm(a,MOD-2),要求a与MOD互质,其中题目给的mod=1e9+9是个质数
归结: 核心思想, 根据取模→用逆元乘法 取代 分数运算
以下是AC代码,复杂度O(log(max(a,b))*k)
还有一种计算方法,连续k个为一个集合,和后面是等比数列
#include<bits/stdc++.h>
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int MOD=1e9+9;
const int INF=0x3f3f3f3f;
ll qm(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=(ans*a%MOD);
a=(a*a)%MOD;
b>>=1;
}
return ans%MOD;
}
char s[N];
int main(void){
ll n,a,b,k;
ll ans=0;
cin >> n>>a>>b>>k;
ll head=qm(a,n);
// cout <<"head="<<head<<endl;
ll inv_a=qm(a,MOD-2);
ll gap=qm(b,k)*qm(inv_a,k)%MOD;
string s;cin>>s;
// cout <<"gap="<<gap<<endl;
for(int i=0;i<(int)s.size();++i){
int flag=1;
if(s[i]=='-') flag=-1;
if(gap==1) ans+=flag*(n+1)/k%MOD *head,ans= ((ans%MOD)+MOD)%MOD;
else{
ans+=flag*head*qm(1-gap,MOD-2)%MOD*(1-qm(gap,(n+1)/k))%MOD;
ans= ((ans%MOD)+MOD)%MOD;
}
head=head*b%MOD*inv_a%MOD;
// cout <<ans <<endl;
}
cout << ans << endl;
return 0;
}