Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 2) C. Alternating Sum

C. Alternating Sum

这里写图片描述

传送门

这题,咋说呢,这位同学,等比数列了解一下。
首先第一点在运算的时候要用快速幂处理一下,基本操作。
之后根据给出的条件我们可以发现两个连续的段有 bkak b k a k 次不同
端的数量是 n+1k n + 1 k
由上我们可以很容易就得知结果为 ans=k1i=0sianibi a n s = ∑ i = 0 k − 1 s i a n − i b i ∗ ans=(n+1k)ki=0bkak a n s = ∑ i = 0 ( n + 1 − k ) k b k a k
或者是 ans=k1i=0sianibi a n s = ∑ i = 0 k − 1 s i a n − i b i ∗ bkakn+1k1bkak b k a k n + 1 k − 1 b k a k

#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define inf int(0x3f3f3f3f)
#define mod int(1e9+9)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson  root << 1
#define rson  root << 1 | 1

char s[200005];

ll n,a,b,k;


ll cal(ll x,ll n)
{
    if(x<0)
    {
        x+=mod;
        x%=mod;
    }
    ll num=x,ans=1;
    for(int i=0; i<64; i++)
    {
        if(1ll<<i&n)
            ans=ans*num%mod;
        num=num*num%mod;
    }
    return ans;
}

ll numa;
ll numb;
ll aa;
ll bb;
ll a1;

void solve()
{
    ll num=cal(aa,k)*cal(b,k)%mod;
    a1+=mod;
    a1%=mod;
    ll sum=0;
    if(num==1)
        sum=(n+1)/k*a1%mod;
    else
        sum=a1*(1-cal(num,(n+1)/k)+mod)%mod*cal(1-num,mod-2)%mod;
    sum+=mod;
    sum%=mod;
    cout<<sum<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie();
    cin>>n>>a>>b>>k;
    cin>>s;
    ll numa=cal(a,n);
    ll numb=1;
    ll aa=cal(a,mod-2);
    ll bb=cal(b,mod-2);
    ll a1=0;
    for(int i=0; i<k; i++)
    {
        if(s[i]=='+')
            a1=(a1+numa*numb%mod)%mod;
        else
            a1=(a1-numa*numb%mod+mod)%mod;
        numa=numa*aa%mod;
        numb=numb*b%mod;
    }
    //solve();
    ll num=cal(aa,k)*cal(b,k)%mod;
    a1+=mod;
    a1%=mod;
    ll sum=0;
    if(num==1)
        sum=(n+1)/k*a1%mod;
    else
        sum=a1*(1-cal(num,(n+1)/k)+mod)%mod*cal(1-num,mod-2)%mod;
    sum+=mod;
    sum%=mod;
    cout<<sum<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值