Codeforces Round #475 (Div. 2) C. Alternating Sum(求逆元)

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 a
and b. Moreover, you are given a sequence s0,s1,…,sn. All values in s are integers 1 or −1. It’s known that sequence is k-periodic and k divides n+1. In other words, for each k≤i≤n it’s satisfied that si=si−k

.

Find out the non-negative remainder of division of n∑i=0sian−ibi
by 109+9

.

Note that the modulo is unusual!
Input

The first line contains four integers n,a,b
and k (1≤n≤109,1≤a,b≤109,1≤k≤105)

.

The second line contains a sequence of length k

consisting of characters ‘+’ and ‘-‘.

If the i
-th character (0-indexed) is ‘+’, then si=1, otherwise si=−1

.

Note that only the first k

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+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:

(n∑i=0sian−ibi)
= 2230−2131+2032

= 7

In the second example:

(n∑i=0sian−ibi)=−1450−1351−1252−1153−1054=−781≡999999228(mod109+9)

解析:由于用到取模,还要做除法运算,所以要用到逆元,我们先把连续的k个值求出来,然后求出公比p,即(b/a)^k,如果p==1那么输出x*sum,p不等于1就还要求下1-p的逆元,然后按等比数列求和公式得出结果
不清楚如何求逆元可以点下这里
一般膜都是素数,所以直接用a^(mod-2)次方求就好了

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rep1(i,b,a) for(int i=b;i>=a;i--)
#define mod 1000000009
#define INF 1000000
using namespace std;
const int N=1e5+100;
int arr[N];
ll fi(ll A,ll n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)
             ans=(ans*A)%mod;
        A=(A*A)%mod;
        n>>=1;
    }
    return ans;
}
int main()
{
    ll n,k,a,b,p,ans,sum=0,t,x;
    string s;
    cin>>n>>a>>b>>k>>s;
    for(int i=0;i<k;i++)
    {
        t=fi(a,n-i)*fi(b,i)%mod;
        if(s[i]=='+')
            sum=(sum+t)%mod;
        else 
            sum=(sum-t+mod)%mod;
    }
    x=(n+1)/k;
    t=(b%mod)*fi(a,mod-2)%mod;
    p=fi(t,k)%mod;
    if(p==1)
    {
        cout<<sum*x%mod<<endl;
        return 0;
    }
    ans=fi(p,x)%mod;
    ans=(1-ans+mod)%mod;
    ans=ans*fi((1-p+mod)%mod,mod-2)%mod;
    cout<<(ans*sum%mod+mod)%mod<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值