CodeForces - 963A Alternating Sum 逆元 等比数列

http://codeforces.com/problemset/problem/963/A

题意:求解ni=0sianibi∑i=0nsian−ibi mod 109+9,si表示正负,并告诉你前k个si的符号,且满足si=sik

题解:令u=ki=0sianibi∑i=0nsian−ibi ,z=(b/a)^k。那么ans=(u+u*z+u*z^2+...+u*z^((n+1)/k-1))。整理得ans=u*(1-z^((n+1)/k))/(1-z)

注意公比z不能等于1,比赛时只判断了a==b的情况,然而在取模和乘逆元等操作下z还有可能变为1的。

其实题目不难,比赛时看到这么少人a,有点不自信了。

代码:

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<bitset>

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>

#include<iomanip>
#include<iostream>

#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 100000 + 5;
const LL mod = 1e9 + 9;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;

LL quick(LL a,LL b){
	LL ans=1;
	a%=mod;
	while(b){
		if(b&1)
			ans=(ans*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
} 

LL quick1(LL a,LL b){
	LL ans=0;
	a%=mod;
	while(b){
		if(b&1)
			ans=(ans+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return ans;
} 

int main(){
	LL n,k;
	LL a,b;
	char s[N];
	scanf("%I64d%I64d%I64d%I64d%s",&n,&a,&b,&k,s+1);
	LL temp,aa,bb;
	LL sum=0,ans=0;
	for(LL i=1;i<=k;i++){
		temp=quick(a,n-i+1)*quick(b,i-1);
		if(s[i]=='+'){
			sum+=temp;
		}
		else{
			sum-=temp;
		}
		sum=(sum+mod)%mod;
	}
	aa=quick(a,k);bb=quick(b,k);
	aa=quick(aa,mod-2);//求逆元 
	temp=quick1(bb,aa);
	if(temp==1){//特判公比为1 
		ans=quick1(sum,(n+1)/k);
		cout<<ans<<endl;
		return 0;
	}
	aa=quick(temp,(n+1)/k)-1;aa=(aa+mod)%mod;
	bb=temp-1;bb=(bb+mod)%mod;
	bb=quick(bb,mod-2);
	temp=quick1(aa,bb);
	ans=quick1(sum,temp);
	ans=(ans+mod)%mod;
	printf("%I64d\n",ans);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值