BZOJ4403: 序列統計【lucas定理+組合數學】

Description

給定三個正整數N、L和R,統計長度在1到N之間,元素大小都在L到R之間的單調不降序列的數量。輸出答案對10^6+3取模的結果。c++

Input

輸入第一行包含一個整數T,表示數據組數。spa

第2到第T+1行每行包含三個整數N、L和R,N、L和R的意義如題所述。code

1≤N,L,R≤10^9,1≤T≤100,輸入數據保證L≤R。ip

Output

輸出包含T行,每行有一個數字,表示你所求出的答案對10^6+3取模的結果。input

Sample Input

2
1 4 5
2 4 5it

Sample Output

2
5
//【樣例說明】知足條件的2個序列爲[4]和[5]。io


思路

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

#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;
}
相關文章
相關標籤/搜索