BZOJ4403: 序列统计【lucas定理+组合数学】

Description

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

Input

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

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

1≤N,L,R≤10^9,1≤T≤100,输入数据保证L≤R。

Output

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

Sample Input

2
1 4 5
2 4 5

Sample Output

2
5
//【样例说明】满足条件的2个序列为[4]和[5]。


思路

推一下式子发现答案是\(\sum_{i=1}^{n}C_{r-l+i}^i=C_{r-l+n+1}^n-1\)

#include<bits/stdc++.h>

using namespace std;

const int Mod = 1e6 + 3;

int f[Mod + 10];
int inv[Mod + 10], fac[Mod + 10];

int add(int a, int b) {
  return (a += b) >= Mod ? a - Mod : a;
}
 
int sub(int a, int b) {
  return (a -= b) < 0 ? a + Mod : a;
}
 
int mul(int a, int b) {
  return 1ll * a * b % Mod;
}
 
int fast_pow(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) res = mul(res, a);
    b >>= 1;
    a = mul(a, a);
  }
  return res;
}

void init() {
  fac[0] = inv[0] = 1;
  for (int i = 1; i < Mod; i++) fac[i] = mul(fac[i - 1], i);
  inv[Mod - 1] = fast_pow(fac[Mod - 1], Mod - 2);
  for (int i = Mod - 2; i >= 1; i--) inv[i] = mul(inv[i + 1], i + 1);
}

int C(int a, int b) {
  return mul(fac[a], mul(inv[b], inv[a - b]));
}

int lucas(int a, int b) {
  if (a < b) return 0;
  if (a < Mod && b < Mod) return C(a, b);
  return mul(C(a % Mod, b % Mod), lucas(a / Mod, b / Mod));
}

int main() {
  freopen("input.txt", "r", stdin);
  init();
  int T; scanf("%d", &T);
  while (T--) {
    int n, l, r;
    scanf("%d %d %d", &n, &l, &r);
    printf("%d\n", sub(lucas(r - l + n + 1, n), 1));
  }
  return 0;
}
posted @ 2018-12-07 21:22 Dream_maker_yk 阅读(...) 评论(...) 编辑 收藏