bzoj 4403(Lucas定理)

传送门
题解:
考虑长度为n,值域为连续m个数的不降子序列。方案有C(n+m-1,n)=C(n+m-1,m-1)种。比如n=4,l=2,r=5,此时m=4,那么就可以视为在{2,3,4,5,x,x,x}中选择n个,比如{2,2,3,3},{2,2,2,3},{2,3,3,3}可以对应3种等价的{2,x,x,3}。
由于组合数有一个公式,如果从n个里选m个,有
C(n,m)=C(n-1,m-1)+C(n-1,m)
从1到n加起来就是:(借用Po爷的图,身边没有公式编辑器或者新版word…)
这里写图片描述
然后上lucas求即可。
注意:最后答案-1,小心有负数!!!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=1e6+3;
int kase;
ll n,l,r,m;
ll fac[MOD+5]={1};
inline void init() {
    for (register int i=1;i<MOD;++i)
        fac[i]=fac[i-1]*i%MOD;
}
inline ll fpow(ll a,ll b,ll p) {
    ll ret=1;
    while (b) {
        if (b&1) ret=ret*a%p;
        b>>=1,a=a*a%p;
    }
    return ret;
}
inline ll lucas(ll n,ll m,ll MOD) {
    ll ret=1;
    while (n&&m) {
        ll nn=n%MOD,mm=m%MOD;
        if (nn<mm) return 0;
        ret=ret*fac[nn]%MOD*fpow(fac[nn-mm]*fac[mm]%MOD,MOD-2,MOD)%MOD;
        n/=MOD,m/=MOD;
    }
    return ret;
}
int main() {
    scanf("%d",&kase);
    init();
    while (kase--) {
        scanf("%lld%lld%lld",&n,&l,&r);
        m=r-l+1;
        printf("%lld\n",(lucas(n+m,m,MOD)+MOD-1)%MOD);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值