cf963 A. Alternating Sum

cf963 A. Alternating Sum_第1张图片
给出 n,a,b,k n , a , b , k .
输入 k k 个数 全是 1 1 1 − 1 的序列 S S .
sianibi ∑ s i a n − i b i 1e9+9 1 e 9 + 9 取模的结果。
数据范围 n,a,b<=109 n , a , b <= 10 9 k<=105 k <= 10 5

直接暴力把表打出来 发现每个数构成了一个等比数列。观察发现公比为 (b/a) ( b / a )
因为是存在循环节的 所以每个循环节之间也是等比数列。循环节的和的公比为 (b/a)k ( b / a ) k

先暴力算出首项
等比数列求和算出中间的 sum=a1(1bin)/(1bi) s u m = a 1 ∗ ( 1 − b i n ) / ( 1 − b i )
暴力算后面多出的部分
复杂度 O(klogn) O ( k l o g n )

#include
using namespace std;

const int MOD=1e9+9;
const int MAXN=1e5+5;
typedef long long ll;

char qwq[MAXN];
int s[MAXN],n,a,b,k;
ll qpow(ll a,ll b){
    ll ans=1,base=a;
    while(b){
        if(b&1)(ans*=base)%=MOD;
        (base*=base)%=MOD;
        b>>=1;
    }
    return ans; 
}

int main(){
    scanf("%d%d%d%d",&n,&a,&b,&k);
    ll bi=qpow(b,k)*qpow(qpow(a,k),MOD-2)%MOD;
    scanf("%s",qwq);
    for(int i=1;i<=k;i++){
        s[i]=qwq[i-1]=='+'?1:-1;
    }
    if(bi==1){
        ll base=0,ans=0,tmp=0;
        for(int i=0;is[i+1]*qpow(a,n-i)*qpow(b,i);
            base%=MOD;base+=MOD;base%=MOD;
        }
        ans=base;
        int lun=(n+1)/k,qidian=lun*k,cnt=0;
        ans=ans*lun;ans%=MOD;ans+=MOD;ans%=MOD;
        for(int i=qidian;i<=n;i++){
            ans+=s[++cnt]*base;
            ans%=MOD;ans+=MOD;ans%=MOD;
        }
        ans+=MOD;ans%=MOD;
        cout<return 0;
    }
    else {
        int lun=(n+1)/k,qidian=lun*k,cnt=0;
        cnt=n-qidian+1;
        ll ans=0;
        for(int i=0;is[i+1]*qpow(a,n-i)*qpow(b,i);
            ans%=MOD;ans+=MOD;ans%=MOD;
        }
        //ll sum=ans*(1-qpow())
        ll sum=ans*(1-qpow(bi,lun))%MOD*qpow(1-bi,MOD-2)%MOD;
        sum+=MOD;sum%=MOD;
        for(int i=1;i<=cnt;i++){
            sum+=s[i+1]*qpow(a,n-qidian)*qpow(b,qidian);
            sum%=MOD;sum+=MOD;sum%=MOD;
            qidian++;
        }
        cout<return 0;
}
/*
621922027 16665164 173157 4676
*/

// (b/a)^k + 

你可能感兴趣的:(数论)