Codeforces Round #475 (Div. 2) C

这题做起来感觉挺坑的。。。大概是不习惯这种数学题吧,也可能是这次前两题太简单了?
anyway,首先如果暴力去算每一个数的值肯定是tle的,注意到这是以k为周期的,那么我们其实可以先算出前k个数的和,然后对于后面的数,每k个一组,每组的和都是上一组的和*(a^k/b^k),这里要求一波乘法逆元。1e9+9是质数所以费马小定理搞一下就行。然后这些和怎么加呢?如果一个个去加也是会tle的…所以就祭出等比数列求和公式吧…注意特判公比为1的情况就行。。。还有就是中间要注意各种数值为负的问题,负数取模似乎会出现很多玄学问题?

#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
const long long  mod=1e9+9;
typedef long long ll;
ll pow(ll x,ll n,ll mod)//快速幂
{
    ll ans=1;
    x%=mod;
    while(n){
        if(n&1)
            ans=ans*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return ans;
}
int main()
{
    ll n,a,b,k;
    string str;
    cin>>n>>a>>b>>k;
    cin>>str;
    int i,j;
    long long fh[100005];//记录符号
    for(i=0;i<str.size();i++){
        if(str[i]=='+')
            fh[i]=1ll;
        else
            fh[i]=-1;
    }
    ll ans=0;
    for(i=0;i<k;i++){
        ans=(ans+fh[i]*pow(a,n-i,mod)*pow(b,i,mod)%mod)%mod;
        ans = (ans + mod) % mod;//这句不能少!保证ans为正!
    }//求前k个
    ll temp=ans;
    ll ak=pow(a,k,mod),bk=pow(b,k,mod);//求a^k,b^k
    ll akn=pow(ak,mod-2,mod);//a^n的乘法逆元,费马小定理
    ll t=akn*bk%mod;
    if(t==1)//特判公比为1
        cout<<temp*((n+1)/k)%mod<<endl;
    else{
        ans=temp*(pow(t,(n+1)/k,mod)-1)%mod*(pow(t-1,mod-2,mod))%mod;//等比数列求和
        cout<<ans<<endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/humveea6/article/details/80058471