Bzoj P4403 序列统计___组合计数+lucas定理

11 篇文章 0 订阅
2 篇文章 0 订阅

题目大意:

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

分析:

元素在 [ L , R ] [L,R] [L,R]选其实相当于在 [ 1 , R − L + 1 ] [1,R-L+1] [1,RL+1]
问题转换成,
i i i个( i ∈ [ 1 , n ] i∈[1,n] i[1,n])球放到 R − L + 1 R-L+1 RL+1个盒子内,盒子可以为空的方案数
a n s = ∑ i = 1 n C i + ( R − L ) R − L ans=\sum_{i=1}^{n}C_{i+(R-L)}^{R-L} ans=i=1nCi+(RL)RL
也就是 a n s = C n + ( R − L ) + 1 R − L + 1 − 1 ans=C_{n+(R-L)+1}^{R-L+1}-1 ans=Cn+(RL)+1RL+11
求C(n,m).但n,m过大时,可用lucas定理

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
 
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define lson(x) x * 2
#define rson(x) x * 2 + 1
 
#define N 1000005
  
using namespace std;
  
typedef long long ll;
 
const int mo = 1000003;
 
int fac[mo+5], inv[mo+5], ans, T;
 
void Pre_Work() {
    fac[0] = 1; rep(i, 1, mo) fac[i] = (ll)fac[i - 1] * i % mo;
    inv[0] = inv[1] = 1; rep(i, 2, mo) inv[i] = (ll)(mo - mo / i) * inv[mo % i] % mo;
    inv[0] = 1; rep(i, 1, mo) inv[i] = (ll)inv[i - 1] * inv[i] % mo;
}
 
int C(int n, int m) {
    if (n < m) return 0;
    if (n > mo || m > mo) return 1ll * C(n / mo, m / mo) * C(n % mo, m % mo) % mo;
    return 1ll * fac[n] * inv[n - m] % mo * inv[m] % mo;
}
 
int main() {
    Pre_Work();
    scanf("%d", &T);
    int n, L, R;
    while (T--) {
        scanf("%d %d %d", &n, &L, &R);
        R = R - L + 1;
        ans = (C(n + R, R) - 1) % mo;
        ans = (ans % mo + mo) % mo;
        printf("%d\n", ans);
    }
    return 0;
}

HOME Back
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值