SRM 582

来源:互联网 发布:我的世界linux服务端 编辑:程序博客网 时间:2024/06/16 17:56

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


1 0