题意:告诉你前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; }