http://codeforces.com/problemset/problem/963/A
题意:求解n∑i=0sian−ibi mod 109+9,si表示正负,并告诉你前k个si的符号,且满足si=si−k。
题解:令u=k∑i=0sian−ibi ,z=(b/a)^k。那么ans=(u+u*z+u*z^2+...+u*z^((n+1)/k-1))。整理得ans=u*(1-z^((n+1)/k))/(1-z)。
注意公比z不能等于1,比赛时只判断了a==b的情况,然而在取模和乘逆元等操作下z还有可能变为1的。
其实题目不难,比赛时看到这么少人a,有点不自信了。
代码:
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<iomanip>
#include<iostream>
#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;
const int N = 100000 + 5;
const LL mod = 1e9 + 9;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
LL quick(LL a,LL b){
LL ans=1;
a%=mod;
while(b){
if(b&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
LL quick1(LL a,LL b){
LL ans=0;
a%=mod;
while(b){
if(b&1)
ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
int main(){
LL n,k;
LL a,b;
char s[N];
scanf("%I64d%I64d%I64d%I64d%s",&n,&a,&b,&k,s+1);
LL temp,aa,bb;
LL sum=0,ans=0;
for(LL i=1;i<=k;i++){
temp=quick(a,n-i+1)*quick(b,i-1);
if(s[i]=='+'){
sum+=temp;
}
else{
sum-=temp;
}
sum=(sum+mod)%mod;
}
aa=quick(a,k);bb=quick(b,k);
aa=quick(aa,mod-2);//求逆元
temp=quick1(bb,aa);
if(temp==1){//特判公比为1
ans=quick1(sum,(n+1)/k);
cout<<ans<<endl;
return 0;
}
aa=quick(temp,(n+1)/k)-1;aa=(aa+mod)%mod;
bb=temp-1;bb=(bb+mod)%mod;
bb=quick(bb,mod-2);
temp=quick1(aa,bb);
ans=quick1(sum,temp);
ans=(ans+mod)%mod;
printf("%I64d\n",ans);
return 0;
}