C. Alternating Sum (逆元+等比数列+快速幂)

题目链接:C. Alternating Sum

题意:就是给出一个n+1长度周期为k的序列,求按照所给公式求和,输出答案。

思路:按周期求,先求出第一个周期 轻易可以推出,每个周期的和是一个等比数列,公比q为(b/a)^k,因为这些数字都比较大,等比数列求和公式a*(q^n-1)*(q-1)^-1;涉及到除法运算,需要用到逆元(逆元素是指一个可以取消另一给定元素运算的元素,在数学里,逆元素广义化了加法中的加法逆元和乘法中的倒数)就可以解决了。(q-1)^-1%mod=(q-1)^(mod-2)%mod。幂运算用快速幂。

代码:

#include<iostream>
#include<string>
#include<cstring> 
using namespace std;
typedef long long ll;
const long long mod=1e9+9;
string s;
ll qpow(ll x,ll n,ll mod)
{
    ll res=1;
    while(n>0)
    {
        if(n&1)res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
int main()
{
    ll n,a,b,k;
    cin>>n>>a>>b>>k;
    cin>>s;
    ll res=0;
    for(int i=0;i<s.size();++i)
    {
        int flag;
        s[i]=='+'?flag=1:flag=-1;
     res=  ((res+flag*qpow(a, n-i, mod) * qpow(b, i, mod) )% mod  + mod) % mod;
    }

ll t = qpow(b, k, mod) * qpow(a, k * (mod - 2), mod) % mod;
    if (t == 1)
    {
        res = res * ((n + 1) / k) % mod;
    }
    else
    {
        res = res * (qpow(t, (n+1)/k, mod) - 1) % mod * qpow(t-1, mod - 2, mod) % mod;
    }
    cout<<res;
    return 0;
 }

猜你喜欢

转载自blog.csdn.net/PinappleMi/article/details/80466220