P4137
dp #数学 #计数dp #组合
从大到小考虑将每个数加入当前的序列
表示 全部加入后, 的方案数
对于一个新的数,有 个,枚举这个数加入的时候分为几段 ,再枚举其中有多少段 加在一个极大递增序列后面
那么 的变化量就是
达到这个的方案数为
其中
直接暴力转移
// Author: xiaruize #ifndef ONLINE_JUDGE bool start_of_memory_use; #endif #include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE clock_t start_clock = clock(); #endif #define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define mms(arr, n) memset(arr, n, sizeof(arr)) #define rep(i, a, n) for (int i = (a); i <= (n); ++i) #define per(i, n, a) for (int i = (n); i >= (a); --i) int max(int a, int b) { if (a > b) return a; return b; } int min(int a, int b) { if (a < b) return a; return b; } const int INF = 0x3f3f3f3f3f3f3f3f; const int MOD = 1000000007; const int N = 2e5 + 10; int c[2005][2005]; void init() { c[0][0] = 1; rep(i, 1, 2000) { c[i][0] = c[i][i] = 1; rep(j, 1, i - 1) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; } } int getc(int x, int y) { if (x < 0 || y < 0 || x < y) return 0; if (x == y || y == 0) return 1; return c[x][y]; } int n, len; int a[2005]; int sum = 0; int dp[40][2005]; void solve() { init(); cin >> n; rep(i, 1, n) cin >> a[i]; cin >> len; dp[0][0] = 1; rep(i, 1, n) { rep(j, 0, len) { int x = a[i]; rep(k, 1, x) { rep(cnt, 0, k) { int rev = k - cnt; int tmp = getc(x - 1, k - 1); int p = x - k; (dp[i][j + p + rev] += dp[i - 1][j] * tmp % MOD * getc(j, cnt) % MOD * getc(sum - j + 1, rev) % MOD) %= MOD; // (dp[i][j + p + 1] += dp[i - 1][j] * tmp % MOD * getc(j, k - 1) % MOD) %= MOD; } } } sum += a[i]; // rep(j, 0, len) cerr << dp[i][j] << ' '; // cerr << endl; } cout << dp[n][len] << endl; } #ifndef ONLINE_JUDGE bool end_of_memory_use; #endif signed main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int testcase = 1; // cin >> testcase; while (testcase--) solve(); #ifndef ONLINE_JUDGE cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl; cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl; #endif return 0; }
本文作者:xiaruize's Blog
本文链接:https://www.cnblogs.com/xiaruize/p/18111029
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步