250:最大的最小,最小的最大之类的题。。二分+验证
600:是个好题,整了好几天才整明白。
题意: 给你n个数1 2 3。。n,代表n个楼,每个数有一种颜色,数值就代表building的高度,现在问有多少的排列满足从左往右看能看到L种颜色。
n <= 1300,显然复杂度应该是平方级别的。
考虑从小到大一个个的占坑,dp[i][j]表示前i个数占完坑后,能看到j种颜色的方案数
显然,一个状态若是合法,应该使得后面的数插进来后是这个状态的延续,比如i j 这两维都应该是非递减的,其实就是i这个数前面不应该有空位了,否则这个空位会被后面的比较大的数占据,然后就破坏了原来的这个状态。
转移起来就是
dp[i][j] = dp[p][?] * A(n - 1 - p, i - p - 1);
用部分和来优化这个dp即可,注意dp[i][1]状态的初始化。
#include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <ctime> using namespace std; class ColorfulBuilding { public: int count(vector <string> color1, vector <string> color2, int L); }; const int N = 1300; const int mod = 1000000009; int dp[N][N], cid[N], col[N], val[N][N], sum[N]; int P[N], inv_P[N]; int power_mod(long long a,long long b,long long c) { long long res = 1; while(b > 0) { if(b & 1) res = res * a % c; b >>= 1; a = a * a % c; } return (int) res; } inline void Add(int &x,int y) { x += y; if(x >= mod) x -= mod; } int ColorfulBuilding::count(vector <string> color1, vector <string> color2, int L){ string s1 = "", s2 = ""; for(int i = 0; i < color1.size(); i++) s1 += color1[i]; for(int i = 0; i < color2.size(); i++) s2 += color2[i]; map<int,int> mp; int totColor = 0; for(int i = 0; i < s1.length(); i++) { col[i + 1] = s1[i] * 256 + s2[i]; if(mp[col[i + 1]] == 0) mp[col[i + 1]] = ++totColor; col[i + 1] = mp[col[i + 1]]; } int n = s1.length(); inv_P[0] = 1; P[0] = 1; for(int i = 1; i <= n; i++) { P[i] = 1LL * P[i - 1] * i % mod; inv_P[i] = 1LL * inv_P[i - 1] * power_mod(i, mod - 2, mod) % mod; } memset(dp, 0, sizeof(dp)); memset(val, 0, sizeof(val)); memset(sum, 0, sizeof(sum)); for(int i = 1; i <= n; i++) { for(int j = 1; j <= i && j <= L; j++) { int add; if(j == 1) { add = 1LL * P[n - 1] * inv_P[n - i] % mod; Add(add, 1LL * val[col[i]][j] * inv_P[n - i] % mod); } else { add = sum[j - 1] - val[col[i]][j - 1]; if(add < 0) add += mod; Add(add, val[col[i]][j]); add = 1LL * add * inv_P[n - i] % mod; } dp[i][j] = add; if(i < n) { add = 1LL * dp[i][j] * P[n - i - 1] % mod; Add(sum[j], add); Add(val[col[i]][j], add); } } } return dp[n][L]; } // Powered by FileEdit // Powered by TZTester 1.01 [25-Feb-2003] // Powered by CodeProcessor