Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 2)C. Alternati(费马小定理求逆元+等比数列求和)

C. Alternating Sum
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given two integers aa and bb. Moreover, you are given a sequence s0,s1,,sns0,s1,…,sn. All values in ss are integers 11 or 1−1. It's known that sequence is kk-periodic and kk divides n+1n+1. In other words, for each kink≤i≤n it's satisfied that si=siksi=si−k.

Find out the non-negative remainder of division of ni=0sianibi∑i=0nsian−ibi by 109+9109+9.

Note that the modulo is unusual!

Input

The first line contains four integers n,a,bn,a,b and kk (1n109,1a,b109,1k105)(1≤n≤109,1≤a,b≤109,1≤k≤105).

The second line contains a sequence of length kk consisting of characters '+' and '-'.

If the ii-th character (0-indexed) is '+', then si=1si=1, otherwise si=1si=−1.

Note that only the first kk members of the sequence are given, the rest can be obtained using the periodicity property.

Output

Output a single integer — value of given expression modulo 109+9109+9.

Examples
input
Copy
2 2 3 3
+-+
output
Copy
7
input
Copy
4 1 5 1
-
output
Copy
999999228
Note

In the first example:

(ni=0sianibi)(∑i=0nsian−ibi) = 22302131+20322230−2131+2032 = 7

In the second example:

(ni=0sianibi)=14501351125211531054=781999999228(mod109+9)(∑i=0nsian−ibi)=−1450−1351−1252−1153−1054=−781≡999999228(mod109+9)


.

题解:
n很大,但是K只有1e5,因此可以算好两头,中间的
每长度为k的一段可以看成一个数,每个数之间成
等比数列,因此可以直接用等比数列求和公式。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=100005;
const ll mod=1e9+9;
char t[maxn];
ll quick(ll a,ll b)
{
    ll r=1;
    while(b)
    {
        if(b%2)r=r*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return r%mod;
}
int main()
{
    ll n,a,b,k;
    scanf("%lld%lld%lld%lld",&n,&a,&b,&k);
    scanf("%s",&t);
    ll sum=0;
    if(n<k)
    {
        for(ll i=0; i<=n; i++)
        {
            ll s=quick(a,n-i)*quick(b,i)%mod;
            if(t[i]=='+')
                sum=(sum+s)%mod;
            else
                sum=(sum-s+mod)%mod;
            //printf("%lld\n",s);
        }
    }
    else
    {
        ll i;
        for(i=0; i<k; i++)
        {
            ll s=quick(a,n-i)*quick(b,i)%mod;
            if(t[i]=='+')
                sum=(sum+s)%mod;
            else
                sum=(sum-s+mod)%mod;
        }
        ll s=sum;
        i--;
        /*for( ;i+k<=n;i+=k)
        {
            s=(s*quick(quick(a,k),mod-2)%mod)*quick(b,k)%mod;
            sum=(sum+s+mod)%mod;
        }*/
        ll q=(quick(quick(a,k),mod-2)%mod)*quick(b,k)%mod;
        ll m=(n-i)/k;
        if(q==1)
            sum=(sum+m*s)%mod;
        else
            sum=(((s*quick(q,m+1)-s)%mod*quick(q-1,mod-2))%mod)%mod;
        int j=0;
        i+=m*k;
        for(i++;i<=n;i++,j++)
        {
            if(t[j]=='+')
            {
                sum=(sum+quick(n-i,i))%mod;
            }
            else
                sum=(sum-quick(n-i,i)+mod)%mod;
        }
    }
    printf("%lld\n",sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/80279953