【BZOJ】【lucas定理】4403: 序列统计

博客围绕代码中的数学计算展开,当长度确定为n时,通过插板法求∑mi=1xi=n的答案为(n+m−1m−1),还提及由(xy)=(x−1y)+(x−1y−1)进行后续操作。

m=RL+1m=R−L+1如果长度确定为nn,相当于求i=1mxi=n,用插板法得答案为(n+m1m1)(n+m−1m−1),然后就是一波骚操作:

(xy)=(x1y)+(x1y1)(xy)=(x−1y)+(x−1y−1)

i=1n(i+m1m1)=(n+m1n)+(n1+m1n1)+...+(m+12)+(m1)+(m0)1=i=1n(i+m1m1)=(n+m1n)+(n1+m1n1)+...+(m+12)+(m+11)1=(n+mn)1∑i=1n(i+m−1m−1)=(n+m−1n)+(n−1+m−1n−1)+...+(m+12)+(m1)+(m0)−1=∑i=1n(i+m−1m−1)=(n+m−1n)+(n−1+m−1n−1)+...+(m+12)+(m+11)−1=(n+mn)−1

由于范围较大,但是注意到模数是质数,直接用lucaslucas定理就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int tt=1000003;
int T,f[tt+6],inv[tt+6];
int C(int x,int y){if(x<y)return 0;return (LL)f[x]*inv[y]%tt*inv[x-y]%tt;}
int lucas(int x,int y){if(!y)return 1;return (LL)C(x%tt,y%tt)*lucas(x/tt,y/tt)%tt;}
int main(){
    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
    f[0]=inv[0]=inv[1]=1;
    for(int i=1;i<=tt;i++)f[i]=(LL)f[i-1]*i%tt;
    for(int i=2;i<=tt;i++)inv[i]=(tt-(LL)tt/i*inv[tt%i]%tt)%tt;
    for(int i=2;i<=tt;i++)inv[i]=(LL)inv[i-1]*inv[i]%tt;
    scanf("%d",&T);
    for(int n,l,r;T;T--)scanf("%d%d%d",&n,&l,&r),printf("%d\n",(lucas(r-l+1+n,n)-1+tt)%tt);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值