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

C. Alternating Sum

题目链接

题意:给出n,a,b,k,第二行给出长度为k一个字符串s,s[i]='+'或者s[i]='-',求  ni=0sianibi∑i=0nsian−ibi 在模109+9109+9

下的值,其中s[i]=s[i%k];

思路:先将字符串s的长度进行扩展到大于int(1e4)的k倍长度的字符串s,将求和的n+1个数分割成(n+1)/k份,剩下的部分再暴力求解。(ps:如果(n+1)%k==0,应该分割成((n+1)/k-1)份,剩下的k份单独求)其中(n+1)/k份是等比数列,记住,不需要用等比数列的求和公式求(因为需要逆元),直接通过比例变换即可求出。

举个栗子:

n=9,a=2,b=3,k=2,s="++";

m=(n+1)/k=5;

因为(n+1)%k==0;

所以分割成m=4份,剩下的2项单独处理。

求一个k份的大小是tmp=2^2*3^0+2^1*3^1;

则第一个k份的大小为2^9*3^0+2^8*3^1=2^7*3^0*tmp;

第二个k份的大小为2^7*3^2+2^6*3^3=2^5*3^2*tmp;

第三个k份的大小为2^5*3^4+2^4*3^5=2^3*3^4*tmp;

第四个k份的大小为2^3*3^6+2^2*3^7=2^3*3^4*tmp;

剩下的2^1*3^8+2^0*3^9单独处理。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000+10;
const int mod=int(1e9)+9;
#define ll long long
ll quick_pow(ll base,ll n) {
	ll ans=1;
	while(n) {
		if(n&1)
			ans=ans*base%mod;
		base=base*base%mod;
		n>>=1;
	}
	return ans%mod;
}
char str[maxn];
int main() {
	int n,a,b,k;
	scanf("%d %d %d %d",&n,&a,&b,&k);
	scanf("%s",str);
	while(k<int(1e4)) {
		for(int i=0; i<k; i++)
			str[i+k]=str[i];
		k<<=1;
	}
	ll ans=0;
	int m=(n+1)/k;
	ll st=n;
	ll ed=0;
	if(m>0) {
		ll tmp=0;
		if(st-k>0) {
			st=st-k;
			for(int i=0; i<k; i++) {
				if(str[i]=='+')
					tmp=(tmp+quick_pow(a,k-i)*quick_pow(b,i)%mod+mod)%mod;
				else
					tmp=(tmp-quick_pow(a,k-i)*quick_pow(b,i)%mod+mod)%mod;
			}
			while(st>0) {
				ans=(ans+(quick_pow(a,st)*quick_pow(b,ed)%mod)*tmp%mod+mod)%mod;
				st-=k;
				ed+=k;
				if(st<=0) {
					st+=k;
					ed-=k;
					break;
				}
			}
		}
	}
	ll sum=0;
	for(int i=st; i>=0; i--) {
		if(str[st-i]=='+')
			sum=(sum+quick_pow(a,i)*quick_pow(b,n-i)%mod+mod)%mod;
		else
			sum=(sum-quick_pow(a,i)*quick_pow(b,n-i)%mod+mod)%mod;
	}
	ans=(ans+sum+mod)%mod;
	printf("%lld\n",ans);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值