Codeforces 963 A. Alternating Sum (逆元)

Description

You are given two integers a a and b. Moreover, you are given a sequence s0,s1,,sn s 0 , s 1 , … , s n . All values in s s are integers 1 or 1 − 1 . It’s known that sequence is k k -periodic and k divides n+1 n + 1 . In other words, for each kin k ≤ i ≤ n it’s satisfied that si=sik s i = s i − k .

Find out the non-negative remainder of division of i=0nsianibi ∑ i = 0 n s i a n − i b i by 109+9 10 9 + 9 .

Note that the modulo is unusual!

 

Input

The first line contains four integers n,a,b n , a , b and k k (1n109,1a,b109,1k105).

The second line contains a sequence of length k k consisting of characters ‘+’ and ‘-‘.

If the i-th character (0-indexed) is ‘+’, then si=1 s i = 1 , otherwise si=1 s i = − 1 .

Note that only the first k k members of the sequence are given, the rest can be obtained using the periodicity property.

 

Output

Output a single integer — value of given expression modulo 109+9.

 

Examples input

2 2 3 3
+-+

 

Examples output

7

 

题意

给定数据 n,a,b,k n , a , b , k 以及 s s ,求解公式的结果。

 

思路

因为 s 中每 k k 段是一样的,于是原公式便等价于一个公比为 akbk 的等比数列前 (n+1)/k ( n + 1 ) / k 项和。

配合逆元求解即可。

 

AC 代码

#include <bits/stdc++.h>
#define IO                       \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 9;

LL a, b, n, k;
char str[maxn];
LL mult(LL a, LL n) {
    LL ans = 1;
    while (n) {
        if (n & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        n >>= 1;
    }
    return ans;
}

void solve() {
    LL ans = 0, res = 0;
    LL inva = mult(a, mod - 2);
    LL pw = mult(a, n);
    LL lun = (n + 1) / k;
    for (int i = 0; i < k; i++) {
        res += (str[i] == '+' ? 1 : -1) * pw % mod;
        res %= mod;
        pw = pw * inva % mod * b % mod;
    }
    LL q = mult(inva, k) * mult(b, k) % mod;
    if (q == 1) {
        ans = res * lun % mod;
    } else {
        LL di = mult((q - 1 + mod) % mod, mod - 2);
        LL de = (mult(q, lun) - 1 + mod) % mod;
        ans = res * de % mod * di % mod;
    }
    ans = ((ans % mod) + mod) % mod;
    cout << ans << endl;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    IO;
#endif // ONLINE_JUDGE

    cin >> n >> a >> b >> k;
    cin >> str;
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值