- From ditoly uncle FJ provincial team training courseware
Statement
There \ (m \) positive integer variables, find how many values program
Such that all variables and not more than \ (S \)
And the front \ (n-\) values of variables does not exceed \ (T \)
The answer to \ (9 + 10 ^ 7 \) modulo
\ (mn \ le1000 \) , \ (m \ 10 ^ 9 \) , \ (t \ 10 ^ 5 \) , \ (s \ s the \ 10 ^ {18} \)
Solution
Because of \ (NT \ S Le \ Le 18 is 10 ^ {} \) , so our solution can be expressed as:
\[\sum_{x_1=1}^t\sum_{x_2=1}^t\dots\sum_{x_n=1}^t\binom{S-\sum_{i=1}^nx_i}{m-n}\]
设 \(s=S-(m-n)+1-\sum_{i=1}^nx_i\)
Noting the number of combinations of the above formula and which is about \ (S \) polynomial, in particular, it is equal to \ (\ frac {s ^ { \ overline {mn}}} {(mn)!} \)
Wherein \ (n ^ {\ overline m } \) represents \ (n-\) a \ (m \) times increase in power, i.e., \ (\ prod_ {i = 0 } ^ {m-1} (n + i) \ )
It can be obtained by a function to generate a first type Stirling number, the polynomial \ (I \) order term coefficient \ (\ frac {\ begin { bmatrix} mn \\ i \ end {bmatrix}} {(mn) !} \) , where \ (\ begin {bmatrix} n \\ m \ end {bmatrix} \) is the Stirling number of the first type, i.e. the \ (n-\) elements into \ (m \) round program number arrayed
After the composition expressed as the number of polynomial form, we determined if we consider the first \ (n-\) variables for all \ (t ^ n \) corresponding to the kinds of values \ (S ^ I \) ( \ ( 0 \ Le i \ Le Mn \) ) the sum, then the problem can be a good solution
Consider the DP: \ (F [I] [J] \) represents \ (x_ {1 \ dots i } \) and all values \ ((S-m + n + 1- \ sum_ {k = 1} ^ ix_k ) ^ j \) and
From the viewpoint of how \ (f [i] \) was transferred to \ (f [i + 1] \)
I.e. the transfer enumeration \ (x_ {i + 1} \) values, set \ (s = S-m + n + 1- \ sum_ {k = 1} ^ ix_k \)
It can be found:
\[\sum_{k=1}^t(s-k)^j=\sum_{k=0}^j(-1)^{j-k}\binom jks^ksum(j-k,t)\]
Wherein \ (SUM (P, n-) = \ sum_ = {I}. 1 ^ Ni ^ P \) , may utilize interpolation \ (O (p) \) is determined
So we have a DP transfer:
\[f[i+1][j]=\sum_{k=0}^j(-1)^{j-k}\binom jksum(j-k,t)f[i][k]\]
The number of combinations apart:
\[\frac{f[i+1][j]}{j!}=\sum_{k=0}^j\frac{(-1)^{j-k}sum(j-k,t)}{(j-k)!}\frac{f[i][k]}{k!}\]
Provided polynomial \ (F_i (X) = \ sum_ {J = 0} ^ {Mn} F [I] [J] X ^ J \) , \ (G (X) = \ sum_ {I = 0} ^ {Mn } \ frac {! (- 1 ) ^ isum (i, t)} {i} x ^ i \)
Then it is easy to get \ (F_n (X) = G (X) n-^ \) , power to the rapid multiplication
Complexity \ (O ((mn) ^ 2 \ log n) \) or \ (O ((mn) ^ 2) \)
Code
#include <bits/stdc++.h>
const int N = 1010, rqy = 1e9 + 7;
typedef long long ll;
ll s;
int t, n, m, l, pw[N][N], f[N], fac[N], inv[N], invt[N], g[N], ans, S[N][N];
int qpow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = 1ll * res * a % rqy;
a = 1ll * a * a % rqy;
b >>= 1;
}
return res;
}
int calc(int T)
{
int sum = 0, res = 0, al = 1;
for (int i = 1; i <= T + 2; i++) al = 1ll * al * (t - i + rqy) % rqy;
for (int i = 1; i <= T + 2; i++)
{
sum = (sum + pw[i][T]) % rqy;
if (i == t) return sum;
int delta = 1ll * al * invt[i] % rqy *
inv[i - 1] % rqy * inv[T + 2 - i] % rqy;
if (T + 2 - i & 1) delta = (rqy - delta) % rqy;
res = (1ll * delta * sum + res) % rqy;
}
return res;
}
int main()
{
std::cin >> s >> t >> n >> m;
l = m - n; s -= l - 1;
f[0] = fac[0] = inv[0] = inv[1] = 1;
for (int i = 1; i <= l + 2; i++) fac[i] = 1ll * fac[i - 1] * i % rqy;
for (int i = 2; i <= l + 2; i++)
inv[i] = 1ll * (rqy - rqy / i) * inv[rqy % i] % rqy;
for (int i = 2; i <= l + 2; i++) inv[i] = 1ll * inv[i] * inv[i - 1] % rqy;
for (int i = 1; i <= l + 2; i++)
{
pw[i][0] = 1;
for (int j = 1; j <= l; j++) pw[i][j] = 1ll * pw[i][j - 1] * i % rqy;
}
for (int i = 1; i <= l + 2; i++) invt[i] = qpow((t - i + rqy) % rqy, rqy - 2);
for (int i = 1; i <= l; i++) f[i] = s % rqy * f[i - 1] % rqy;
for (int i = 0; i <= l; i++) f[i] = 1ll * f[i] * inv[i] % rqy;
for (int i = 0; i <= l; i++)
{
g[i] = 1ll * calc(i) * inv[i] % rqy;
if (i & 1) g[i] = (rqy - g[i]) % rqy;
}
while (n)
{
if (n & 1) for (int i = l; i >= 0; i--)
{
f[i] = 1ll * f[i] * g[0] % rqy;
for (int j = 1; j <= i; j++)
f[i] = (1ll * f[i - j] * g[j] + f[i]) % rqy;
}
for (int i = l; i >= 0; i--)
{
g[i] = 1ll * g[i] * g[0] % rqy;
if (i) g[i] = (g[i] + g[i]) % rqy;
for (int j = 1; j < i; j++)
g[i] = (1ll * g[i - j] * g[j] + g[i]) % rqy;
}
n >>= 1;
}
S[0][0] = 1;
for (int i = 1; i <= l; i++)
for (int j = 1; j <= i; j++)
S[i][j] = (1ll * S[i - 1][j] * (i - 1) + S[i - 1][j - 1]) % rqy;
for (int i = 0; i <= l; i++)
ans = (1ll * f[i] * fac[i] % rqy * S[l][i] + ans) % rqy;
return std::cout << 1ll * ans * inv[l] % rqy << std::endl, 0;
}