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