1657:序列统计(lucas)

1657:序列统计

时间限制: 1000 ms 内存限制: 524288 KB
提交数: 178 通过数: 92
【题目描述】
原题来自:BZOJ 4403

给定三个正整数 N,L 和 R,统计长度在 1 到 N 之间,元素大小都在 L 到 R 之间的单调不降序列的数量。输出答案对 106+3 取模的结果。

【输入】
输入第一行包含一个整数 T,表示数据组数。

第二到第 T+1 行每行包含三个整数 N,L 和 R,N,L 和 R 的意义如题所述。

【输出】
输出包含 T 行,每行有一个数字,表示你所求出的答案对 106+3 取模的结果。

【输入样例】
2
1 4 5
2 4 5
【输出样例】
2
5
【提示】
样例说明

对于第一组输入,满足条件的两个序列为 {4},{5}。

数据范围与提示:

对于全部输入,1≤N,L,R≤109,1≤T≤100,输入数据保证 L≤R。

#include <iostream>
using namespace std;
#define ll long long 
const ll mod=1e6+3;
const ll maxn=mod+2;
ll list[maxn];
ll revs[maxn];
inline ll ext_gcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1;y=0;
		return a;
	}
	ll r=ext_gcd(b,a%b,y,x);//x=y' y=x'-(a/b)*y' ->  y=x' x=y'
	y-=(a/b)*x;
	return r;
 } 
ll res(ll a)
{
	ll x,y;
	ext_gcd(a,mod,x,y);
	return x>0?x%mod:(x%mod+mod)%mod;
}
ll pows(ll x,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)
		ans=ans*x%mod;
		x=x*x%mod;
		b>>=1;
	}
	return ans;
}
void init()
{
	list[0]=1;
	revs[0]=res(list[0]);
	for(int i=1;i<maxn;i++)
	{
		list[i]=list[i-1]*i%mod;
		revs[i]=res(list[i]);
	}
}
ll getC_(ll m,ll n)
{
	ll ansm=1,ansn=1;
	for(int i=1;i<=n;i++)
	{
		ansm=ansm*(m-i+1);
		ansn=ansn*i;
	}
	return ansm/ansn;
	
}

ll getA(ll m,ll n)
{
	if(m<n)return 0;
	return list[m]*revs[m-n]%mod;
}
ll getC(ll m,ll n)
{
	if(m<n)return 0;
	return getA(m,n)*revs[n]%mod;
}
ll lucas(ll m,ll n)
{
	if(n==0)return 1;
	else return getC(m%mod,n%mod)*lucas(m/mod,n/mod)%mod;
}
int main(int argc, char** argv) {
	init();
	int t;
	cin>>t;
	while(t--)
	{
		ll x,l,r;
		cin>>x>>l>>r;
		ll len=(r-l+1);
		cout<<(lucas(len+x,x)-1+mod)%mod<<endl;
		
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值