Solution
题目的意思就是要求
[xk]∏i=0n(ix+1)
设 fn,k=[xk]∏ni=0(ix+1) ,则有
fn,kfn,k−fn−1,k==fn−1,k+nfn−1,k−1nfn−1,k−1
把
n
看作变量,那么因为前面DP复杂度是 O(n2) ,所以复杂度还是得 O(n2) 。。。
真难过刚开始打 O(n) 的插值还打错了QAQ。。
// BEGIN CUT HERE
// END CUT HERE
#line 5 "CandyDrawing.cpp"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 6060;
int fac[N], inv[N];
int pre[N], suf[N];
int f[N][N];
int g[N];
int n, k, MOD, ans;
inline void Add(int &x, int a) {
x = ((ll)x + a) % 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);
}
class CandyDrawing {
public:
inline void Pre(int n) {
inv[1] = 1;
for (int i = 2; i <= n; i++)
inv[i] = (ll)(MOD - MOD / i) * inv[MOD % i] % MOD;
}
inline int sgn(int x) {
return (x & 1) ? MOD - 1 : 1;
}
/* inline int Inter(int *f, int k, int x) {
pre[0] = suf[0] = 1;
for (int i = 1; i <= k; i++)
pre[i] = ((ll)x - i + MOD) * pre[i - 1] % MOD;
for (int i = 1; i <= k; i++)
suf[i] = ((ll)x - k + i - 1 + MOD) * suf[i - 1] % MOD;
int res = 0;
for (int i = 0; i <= k; i++) {
int s = (ll)pre[i - 1] * suf[k - i] % MOD * f[i] % MOD,
t = (ll)inv[i - 1] * inv[k - i] % MOD;
Add(res, (ll)s * t % MOD * sgn(k - i) % MOD);
}
return res;
}*/
inline int Inter1(int *f, int k, int x) {
int res = 0;
for (int j = 0; j <= k; j++) {
int pro = 1;
for (int i = 0; i <= k; i++) {
if (i < j) pro = (ll)pro * inv[j - i] % MOD * (x - i + MOD) % MOD;
if (i > j) pro = (ll)pro * -inv[i - j] % MOD * (x - i + MOD) % MOD;
}
res = ((ll)pro * f[j] + res) % MOD;
}
return ((ll)res + MOD) % MOD;
}
int findProbability(int _N, int _K, int _MOD) {
n = _N; k = _K; MOD = _MOD; Pre(k * 2);
f[0][0] = 1;
for (int i = 1; i <= k * 2; i++) {
f[i][0] = 1;
for (int j = 1; j <= i; j++)
f[i][j] = ((ll)i * f[i - 1][j - 1] + f[i - 1][j]) % MOD;
}
for (int i = 0; i <= k * 2; i++) g[i] = f[i][k];
return Inter1(g, k * 2, n);
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = 2; int Arg1 = 1; int Arg2 = 1000000007; int Arg3 = 3; verify_case(0, Arg3, findProbability(Arg0, Arg1, Arg2)); }
void test_case_1() { int Arg0 = 3; int Arg1 = 2; int Arg2 = 1000000007; int Arg3 = 11; verify_case(1, Arg3, findProbability(Arg0, Arg1, Arg2)); }
void test_case_2() { int Arg0 = 10; int Arg1 = 4; int Arg2 = 1000000007; int Arg3 = 157773; verify_case(2, Arg3, findProbability(Arg0, Arg1, Arg2)); }
void test_case_3() { int Arg0 = 1000000000; int Arg1 = 1000; int Arg2 = 1000000009; int Arg3 = 629516825; verify_case(3, Arg3, findProbability(Arg0, Arg1, Arg2)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main(void) {
CandyDrawing ___test;
___test.run_test(-1);
system("pause");
}
// END CUT HERE