Codeforces 963A Alternating Sum(找规律)

题目链接:Alternating Sum

题意

给定 a,b a , b 的值,以及 n+1 n + 1 项系数 s0,s1,,sn s 0 , s 1 , ⋯ , s n ,所有系数不是 1 1 就是 1,这 n+1 n + 1 项系数是以 k k 为循环节的,且 k|n+1,给定前 k k 项系数,求公式 i=0nsianibimod109+9 的值。

输入

第一行为 4 4 个整数 n,a,b,k (1n109,1a,b109,1k105),第二行包含一个长度为 k k 的字符串,字符串只包含 +- 这两种字符,表示系数的正负。

输出

输出计算结果。

样例

输入
2 2 3 3
+-+
输出
7
提示
(i=0nsianibi)=22302131+2032=7

输入
4 1 5 1
-
输出
999999228
提示
$(\sum_{i=0}^ns_ia^{n-i}b^i)=-1^45^0-1^35^1-1^25^2-1^15^3-1^05^4=-781=999999228

\mod10^9+9$。|

题解

只观察每 k k 个数字,会发现这这些项是以 (ba)k 为公比的等差数列,套上等比数列求和公式就可以得到答案,注意公比为 1 1 <script type="math/tex" id="MathJax-Element-17">1</script> 的情况。

过题代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
using namespace std;

#define LL long long
const LL MOD = 1000000009;
const int maxn = 100000 + 100;
LL n, a, b, k;
char str[maxn];

LL fast_pow(LL res, LL n) {
    LL ans;
    for(ans = 1; n != 0; n >>= 1) {
        if(n % 2 == 1) {
            ans = (ans * res) % MOD;
        }
        res = (res * res) % MOD;
    }
    return ans;
}

void exgcd(LL a, LL b, LL &x, LL &y) {
    if(b == 0) {
        x = 1;
        y = 0;
        return ;
    }
    exgcd(b, a % b, y, x);
    y -= x * (a / b);
}

LL inv(LL x) {
    LL xx, yy;
    exgcd(x, MOD, xx, yy);
    xx = ((xx % MOD) + MOD) % MOD;
    return xx;
}

int main() {
    #ifdef LOCAL
    freopen("test.txt", "r", stdin);
    #endif // LOCAL

    while(scanf("%I64d%I64d%I64d%I64d", &n, &a, &b, &k) != EOF) {
        if(k >= n + 1) {
            k = n + 1;
        }
        scanf("%s", str);
        LL tmp = 0;
        LL inva = inv(a);
        LL invb = inv(b);
        LL aa = fast_pow(a, n + 1);
        LL bb = invb;
        for(LL i = 0; i < k; ++i) {
            aa = (aa * inva) % MOD;
            bb = (bb * b) % MOD;
            if(str[i] == '+') {
                tmp += (aa * bb) % MOD;
            } else {
                tmp -= (aa * bb) % MOD;
            }
            tmp = ((tmp % MOD) + MOD) % MOD;
        }
        LL q = fast_pow((inva * b) % MOD, k);
        LL nn = (n + 1) / k;
        if(q == 1) {
            tmp = (nn * tmp) % MOD;
        } else {
            LL fenzi = (((1 - fast_pow(q, nn)) % MOD) + MOD) % MOD;
            LL fenmu = ((1 - q) % MOD + MOD) % MOD;
            fenzi = (fenzi * inv(fenmu)) % MOD;
            tmp = (tmp * fenzi) % MOD;
        }
        printf("%I64d\n", tmp);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值