Codeforces 964C Alternating Sum
You are given two integers a and b. Moreover, you are given a sequence s0,s1,…,sn. All values in s are integers 1 or −1. It's known that sequence is k-periodic and k divides n+1. In other words, for each k≤i≤n it's satisfied that si=si−k.Find out the non-negative remainder of division of n∑i=0sian−ibi
Input
The first line contains four integers n,a,b and k (1≤n≤109,1≤a,b≤109,1≤k≤105).
The second line contains a sequence of length k consisting of characters '+' and '-'. If the i -th character (0-indexed) is'+', then si=1, otherwise si=−1.
Note that only the first k
Output a single integer — value of given expression modulo 109+9.
ExamplesInput2 2 3 3 +-+Output
7Input
4 1 5 1 -Output
999999228Note
In the first example:
(n∑i=0sian−ibi)
= 2230−2131+2032= 7
In the second example:
(n∑i=0sian−ibi)=−1450−1351−1252−1153−1054=−781≡999999228(mod109+9)
題意:
給你一個公式,給你一個k個字元,表示前k個的加減規則,然後就是讓你求(n+1)/k 這段長度中的值,對1e9+9取餘。
解題思路:
我們可以很快的從題目中看到這是一個等比數列,求前(n+1)/k項的和,比例係數為(b/a)^k 但是我們不能忘記了這個比例係數為1的特殊情況。然後就是用快速冪加速,用擴充套件GCD求逆元。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
const long long mo=1e9+9;
const int maxn=1e5+10;
ll n,a,b,k;
char ch[maxn];
ll find(ll a,ll t){
ll res=1;
while(t){
if(t&1) res=res*a%mo;
a=(a*a)%mo;
t/=2;
}
return (res+mo)%mo;
}
ll ex_gcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1,y=0;return a;
}
ll te=ex_gcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-(a/b)*x;
return te;
}
ll NY(ll nu){
ll x,y;
ex_gcd(nu,mo,x,y);
return (x+mo)%mo;
}
int main(){
int i,j;
scanf("%I64d%I64d%I64d%I64d",&n,&a,&b,&k);
scanf("%s",ch);
ll ans=0,m=(n+1)/k;
for(i=0;i<k;i++){
ll t1=find(a,n-i),t2=find(b,i);
ll temp=t1*t2%mo;
if(ch[i]=='+')
ans+=temp;
else
ans-=temp;
ans+=mo;
ans%=mo;
}
ll q=find(NY(a),k)*find(b,k)%mo;
if(q==1){
ans=ans*m%mo;
}
else{
long long t1=NY(q-1)%mo;
ans=(ans*(find(q,m)-1)%mo)*t1%mo;
ans%=mo;
}
ans=(ans+mo)%mo;
printf("%I64d\n",ans);
return 0;
}
.