Codeforces 964 C. Alternating Sum (求和+逆元)

2024-01-25 00:18

本文主要是介绍Codeforces 964 C. Alternating Sum (求和+逆元),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

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=sik. s i = s i − k .
Find out the non-negative remainder of division of ni=0sianibi ∑ i = 0 n s i a n − i b i 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. 10 9 + 9.

Examples

input
2 2 3 3
+-+
output
7
input
4 1 5 1
-
output
999999228

题目描述

ni=0sianibi ∑ i = 0 n s i a n − i b i ,其中si由给定的符号字符串确定,若对应位置为‘+’,则si=1,否则si=-1,字符串的长度为k,当i大于k时,从头循环获取对应位置.

解题思路

首先看到k的范围是1e5,便可以考虑从这里入手去求解,当n>k时,可以发现每k个连续的数之间成比例,且比值为 bkak b k a k ,这样便可以构成一个公比为 bkak b k a k 的,项数为num=(n+1)/k 的等比数列,从头循环一遍k便可得出首项,然后等比数列求和.剩余的(n+1)-num*k即无法构成等比数列的数再单独遍历求和即可.
Ps:求逆元是肯定的,但是要注意判断公比的逆元是否为1.不要傻乎乎的在求逆元之前判断(ಥ﹏ಥ)C题又没达成(ಥ﹏ಥ)

代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn =1e5+7;
const ll mod=1e9+9;
#define IO ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);
char str[maxn];
ll quick_pow(ll a,ll b)
{ll ans=1;while(b){if(b%2)ans=(ans*a)%mod;a=(a*a)%mod;b/=2;}return ans;
}
int main()
{IO;ll n,a,b,k;cin>>n>>a>>b>>k>>str;ll ans=0;ll res=0;ll x=quick_pow(a,n),xx=quick_pow(a,mod-2),xxx=1;  //a^n,a的逆元ll y=quick_pow(b,n),yy=quick_pow(b,mod-2),yyy=1;  //同上int mark;for(int i=0; i<k; i++)      //前k个的和{if(str[i]=='+') mark=1;else mark=-1;res=(res+mark*x*yyy)%mod;x=(x*xx)%mod;yyy=(yyy*b)%mod;}ll num=(n+1)/k;                              //该等比数列含有num个项ll divide=quick_pow(quick_pow(a,k),mod-2);   //a^k的逆元ll mul=quick_pow(b,k);                       //b^kll q=mul*divide%mod;                         //公比if(q==1)ans=(num*res)%mod;elseans=(res*((1-quick_pow(q,num))%mod)%mod*quick_pow(1-q,mod-2)%mod+mod)%mod;num=(n+1)-num*k;                             //除去可构成等比数列之后的剩余项ll id=num-1;                                 //由后向前加和res=0;for(ll i=0; i<num; i++){if(str[id]=='+') mark=1;else mark=-1;res=(res+mark*y*xxx)%mod;y=(y*yy)%mod;xxx=(xxx*a)%mod;id--;}ans=((ans+res)%mod+mod)%mod;cout<<ans<<endl;return 0;
}

这篇关于Codeforces 964 C. Alternating Sum (求和+逆元)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/641511

相关文章

hdu4828(卡特兰数+逆元)

这题的前几个数据分别为1,2,5,14,32......................然后确定这是个卡特兰数列 下面来介绍下卡特兰数,它的递推式为f[i+1] = f[i]*(4*n - 6)/n,其中f[2] = f[3] =1;f[4] = 2;f[5] = 14;f[6] = 32.................................. 但是这题的n太大了,所以要用到逆元,

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

最大流=最小割=最小点权覆盖集=sum-最大点权独立集

二分图最小点覆盖和最大独立集都可以转化为最大匹配求解。 在这个基础上,把每个点赋予一个非负的权值,这两个问题就转化为:二分图最小点权覆盖和二分图最大点权独立集。   二分图最小点权覆盖     从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。 建模:     原二分图中的边(u,v)替换为容量为INF的有向边(u,v),设立源点s和汇点t

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

如何导入sun.misc.BASE64Encoder和sum.misc.BASE64Decoder

右击项目名--->Build Path--->Configure Build Path...--->java Build Path--->Access rules:1 rule defined,added to all librar...   --->Edit --->Add...

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1:输入:a = "11", b = "1"输出:"100"示例 2:输入:a = "1010", b = "1011"输出:"10101" 算法设计 可以从低位到高位(从后向前)计算,用一个变量carry记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对