Solution S o l u t i o n
这是个有序的序列,只要计算一个数出现了最多次,最后乘
m
m
就好了。
枚举出现了次。
那剩下的就是
∏i=1m−1(∑j=0k−1xj)=(1−xk)m−1(1−x)1−m
∏
i
=
1
m
−
1
(
∑
j
=
0
k
−
1
x
j
)
=
(
1
−
x
k
)
m
−
1
(
1
−
x
)
1
−
m
负指数幂的话:
(1+x)−n=∑k=0∞(−1)k(n+k−1k)xk
(
1
+
x
)
−
n
=
∑
k
=
0
∞
(
−
1
)
k
(
n
+
k
−
1
k
)
x
k
枚举两边的幂指数,是个调和级数。复杂度 O(Tnlogn) O ( T n log n )
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
const int N = 202020;
typedef long long ll;
int fac[N], ifac[N];
int n, lo, hi, test, ans;
inline void pre(int n) {
ifac[1] = 1;
for (int i = 2; i <= n; i++)
ifac[i] = (ll)(MOD - MOD / i) * ifac[MOD % i] % MOD;
fac[0] = ifac[0] = 1;
for (int i = 1; i <= n; i++) {
fac[i] = (ll)fac[i - 1] * i % MOD;
ifac[i] = (ll)ifac[i - 1] * ifac[i] % MOD;
}
}
inline int C(int n, int m) {
if (n < 0 && m >= 0)
return (m & 1) ? MOD - C(-n + m - 1, m) : C(-n + m - 1, m);
if (n < m) return 0;
return (ll)fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}
inline void add(int &x, int a) {
x += a; while (x >= MOD) x -= MOD;
}
inline int pow(int a, int b) {
int c = 1;
while (b) {
if (b & 1) c = (ll)c * a % MOD;
b >>= 1; a = (ll)a * a % MOD;
}
return c;
}
inline int inv(int x) {
return pow(x, MOD - 2);
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
cin >> test; pre(200000);
while (test--) {
cin >> n >> lo >> hi;
int m = hi - lo + 1;
ans = 0;
for (int k = 1; k <= n; k++)
for (int j = 0; n - k - j >= 0 && j / k <= m - 1; j += k) {
int up = C(m - 1, j / k);
if ((j / k) & 1) up = MOD - up;
int down = C(m + n - k - j - 2, n - k - j);
add(ans, (ll)up * down % MOD);
}
ans = (ll)ans * m % MOD;
cout << ans << endl;
}
return 0;
}