【区间DP】 HDU 5396 Expression
题意:给出n个数,n-1个操作方法,求(n-1)!的操作顺序得到的和是多少
思路:
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; template <class T> inline bool rd(T &ret) { char c; int sgn; if(c = getchar() , c == EOF) return false; while(c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return true; } const int N = 101; const int MOD = 1e9 + 7; int n; int a[N]; ll dp[N][N], f[N], C[N][N]; char op[N]; int main() { f[0] = 1; C[0][0] = 1; for (int i = 1; i < N; ++i) { f[i] = f[i - 1] * i % MOD; C[i][0] = C[i][i] = 1; for (int j = 1; j < i; ++j) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; } while(1 == scanf("%d", &n)) { for (int i = 1; i <= n; ++i) rd(a[i]); scanf("%s", op + 1); memset(dp, 0, sizeof dp); for (int i = 1; i <= n; ++i) dp[i][i] = a[i]; for(int l = 2; l <= n; ++l) for(int i = 1; i <= n - l + 1; ++i) { int j = i + l - 1; ll now = 0; for(int k = i; k < j; ++k) { if (op[k] == '*') now = dp[i][k] * dp[k + 1][j] % MOD; else if (op[k] == '+') now = (f[j - k - 1] * dp[i][k] % MOD + f[k - i] * dp[k + 1][j] % MOD) % MOD; else now = (f[j - k - 1] * dp[i][k] % MOD - f[k - i] * dp[k + 1][j] % MOD + MOD) % MOD; dp[i][j] = (dp[i][j] + now * C[l - 2][k - i]) % MOD; } } printf("%d\n", dp[1][n]); } return 0; }