Codeforces Round #475 Div1 A题题解(每日一题)

 

中文传送门 

题目来源

思路:

首先打表,会发现这道题是一个循环节问题,每一个周期会构成一个等比数列,然后特判一下公比是否为1即可,若公比为1,ans = q * m(周期数);否则,利用等比数列的前n项求和公式求出ans即可。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1e9+9;
const ll N=1e5+10;

ll n,a ,b,k;
char s[N];

ll qmi(ll a,ll b){
    ll ans=1;
    while(b){
        if(b & 1){
            ans = ans * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
ll inv(ll x){
    return qmi(x,mod-2);
}
int main()
{
    scanf("%lld%lld%lld%lld",&n,&a,&b,&k);
    scanf("%s",s);
    
    ll m = (n + 1)/k; //循环节的个数
    ll a1 = 0,t1,t2,tmp,ans;
    for(ll i = 0;i < k;i ++){
        t1 = qmi(a,n-i);
        t2 = qmi(b,i);
        a1 += (s[i]=='-'?-1:1) * t1 * t2 % mod;
        a1 = (a1 + mod) % mod;
    }
    
    //a1 表示第一个循环结的值,即等比数列的第一项
    
    ans = a1;
    ll q = qmi(b,k);
    q = q * qmi(inv(a),k)%mod;
    // q 表示 公比
    if(q==1){
        ans = a1 * m % mod; // 如果公比为1的话直接让第一个循环节的值 * 循环节的个数
    }else{ // 如果公比不为一的话
        ans = a1;
        ans=ans * (qmi(q,m)-1) % mod;
        ans=ans * inv(q-1) % mod;
        // ans 为等比数列前n项的和
    }
    printf("%lld\n",ans);
}

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值