Div2  AlienAndSetDiv2   1000 pts

题意:1~2N的数分成2个数组A,B,并且数组中按增序排列,同时满足|A[i] - B[i]| <= K,问有多少种方法?

分析:从大到小依次决定每个数的放置位置,每次可以放在A或B中剩余的较高位置,当决定第i个数时,i+K+1,应该是已经匹配了,

那么只剩下i+1~i+K最多K个数处于未匹配的位置,用一个整数st表示,那么对于第i个数的转移情况,可以放置在某个数组中,

使他处于未匹配状况或者让他匹配.

dp[i][st]表示i个数需要划分,且i+1~i+K+1的未匹配情况用st的表示的方案数.

代码:

 const int MOD = (int)1e9 + ;
const int maxn = *;
const int maxm = (<<) + ;
int dp[maxn][maxm]; class AlienAndSetDiv2{
public:
int K, N, M;
int dfs(int n, int st) {
int &res = dp[n][st];
if (res != -) return res;
res = ;
if (st&(<<(K-))) {
res = dfs(n-, (st<<) % M);
} else {
if (st == ) {
res = dfs(n-, );
} else {
res = dfs(n-, st<<|);
int highBit = K-;
while (!((<<highBit) & st)) highBit--;
res = (res + dfs(n-, (st^(<<highBit))<<)) % MOD;
}
}
if (st == ) res = res*%MOD;
return res;
}
int getNumber(int N, int K) {
memset(dp, -, sizeof dp);
dp[][] = ;
for (int i = ; i < maxm; i++) dp[][i] = ;
M = (<<K);
this->K = K;
this->N = N; return dfs(*N, );
}
};

Div1 AlienAndHamburgers  250pts

题意:n种物品,每种物品有两个值taste[i],type[i]分别表示其美味值和类型,要求从中选出一些物品,使得类型数*美味值总和最大.

分析: 按类型排序,将类型相同的物品安排在连续一段考虑,对于第i个物品,如果选中,需要考虑前面一个选中的物品j, 及之前选中的类型总数,

如果j的类型和i的类型不同,那么选中前一个物品j的时候,选中的类型数比当前少1;否则就和当前类型数目一样.

设立状态表示dp[i][x][y] 表示选中第i的时候,选中的类型为x,选择的类型数为y的最大值.

代码:

 typedef long long LL;
typedef unsigned US;
typedef pair<int, int> PII;
typedef map<PII, int> MPS;
typedef MPS::iterator IT;
const int maxn = ;
int dp[maxn][maxn][maxn];
int vis[];
bool mark[maxn][maxn][maxn];
int cnt;
struct Node {
int val, t;
Node() {}
Node (int val, int t) {
if (!vis[t]) {
vis[t] = ++cnt;
}
this->t = vis[t];
this->val = val;
}
bool operator < (const Node &o) const {
return t < o.t;
}
} a[maxn];
class AlienAndHamburgers {
public:
int n;
int dfs(int pos, int x, int y) {
int &res = dp[pos][x][y];
if (mark[pos][x][y]) return res;
mark[pos][x][y] = true;
res = -inf;
if (x == || y == ) return res;
for (int i = ; i < pos; i++) {
int nx = a[i].t;
int ny = y - !(nx == x);
int z = dfs(i, nx, ny);
if (res < (z == -inf ? 1LL * -inf : (ny == ? 1LL * y * a[pos].val : (0LL + z / ny + a[pos].val) * y)))
res = (z == -inf ? 1LL * -inf : (ny == ? 1LL * y * a[pos].val : (0LL + z / ny + a[pos].val) * y));
}
return res;
} int getNumber(vector <int> type, vector <int> taste) {
// memset(dp, -1, sizeof dp);
memset(mark, false, sizeof mark); cnt = ;
for (int i = ; i < maxn; i++) {
for (int j = ; j < maxn; j++) {
for (int k = ; k < maxn; k++)
dp[k][i][j] = -inf;
mark[][i][j] = true;
}
}
dp[][][] = ; memset(vis, , sizeof vis); n = (int)type.size(); for (int i = ; i < n; i++) {
a[i + ] = Node(taste[i], type[i]);
}
a[].t = a[].val = ;
sort(a + , a + n + );
int ans = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= a[i].t; j++)
ans = max(ans, dfs(i, a[i].t, j));
return ans;
}
};

Div1 AlienAndSetDiv1    450pts

题意:Div2 1000pts升级版,不同的是题目条件|A[i]-B[i]| <= K 变成了|A[i]-B[i]| >= K.不过分析过程还是差不多的.

分析:同样的从2N 到1按照从大到小的顺序进行安排,从A,B的高位往下进行放置.由于两个数要相差K以上才能配对,因此当考虑第i个数的时候,

对于尚未配对且满足>=i+K的数此时是可以和剩下的任意数配对的,而i+1~i+K-1之间的数时需要继续等待的,因此此时状态表示变成了dp[i][st][j],表示

分配剩下的i个数时,>=i+K的个数有j个,i+1~i+K-1之间的状态是st,这样只需要建立状态转移即可.

代码:

 const int maxn =  + ;
const int maxm = ( << ) + ;
const int MOD = ; int dp[maxn][maxn][maxm]; class AlienAndSetDiv1 {
public:
int N, K, M;
int dfs(int n, int m, int st) {
int &res = dp[n][m][st];
if (res != -) return res;
res = ;
if (K == ) {
res = dfs(n - , m + , );
if (m > )
res = (res + dfs(n - , m - , )) % MOD;
} else {
if (st == ) {
if (m == ) {
res = dfs(n - , K == , K != );
} else {
res = dfs(n - , m - , );
res = (res + dfs(n - , m + (K == ), K != )) % MOD;
}
} else {
if (m == ) {
res = dfs(n - , ((st & ( << (K - ))) != ) + (K == ), (st << | (K != )) % M); } else {
res = dfs(n - , m - + ((st & ( << (K - ))) != ), (st << ) % M);
res = (res + dfs(n - , m + (K == ) + ((st & ( << (K - ))) != ), (st << | (K != )) % M)) % MOD;
}
}
}
if (st == && m == ) res = res * % MOD;
return res;
}
int getNumber(int N, int K) {
memset(dp, -, sizeof dp);
for (int i = ; i < maxn; i++)
for (int j = ; j < maxm; j++)
dp[][i][j] = ;
dp[][][] = ;
M = << (K - );
this->N = N;
this->K = K;
return dfs( * N, , );
}
};

Div1 AlienAndPermutation 1000pts

题意:给定一个数组P为1~N数字的排列,最多可以进行K次操作:每次选取一个区间,将区间中的数替换成该区间内的数的最大值,最后能够得到不同的数组S.

分析:要解决这个题目首先要发现操作后的数组的性质,

1. S中满足S[j] = P[i]的位置构成连续序列

2. P[i]和P[j]的连续序列在S中相对位置不变

3. P[i]在S中的连续序列l~r满足对于任意处于l~r范围内的jP[j] <= Pi]

4. 对于操作后的序列S,有多少不同的值则需要多少次操作,这其中应该除开长度为1,且i = j的那些元素构成的序列.

下面设立状态表示f(i, j, k, d)表示已经决定P中前i个元素在S中的位置,S中前j个位置已经被占领,剩下k次操作的方案数,当然每个P[i]值最多算做一次操作,用一维d记录是否已经消耗了操作.

j = n 时,res = 1

否则如果i = n,res = 0.

其他情况:

如果S[j]不等于P[i]的值,转移到f(i+1, j, k, 0);否则

对于d = 1 or i == j,转移到f(i, j+1, k, d), 否则f(i, j+1, k-1, 1).

代码:

 typedef long long LL;
typedef unsigned US;
typedef pair<int, int> PII;
typedef map<PII, int> MPS;
typedef MPS::iterator IT;
const int MOD = ;
const int maxn = ;
int dp[maxn][maxn][maxn][];
int l[maxn], r[maxn]; class AlienAndPermutation{
public:
int n, K;
int dfs(int x, int y, int k, int d) {
int &res = dp[x][y][k][d];
if (res != -) return res;
if (y == n) return res = ;
if (x == n) return res = ;
res = ;
res = dfs(x+, y, k, );
if (l[x] <= y && y <= r[x]) {
if (d == || x == y)
res = (res + dfs(x, y+, k, d)) % MOD;
else if (k > ) res = (res + dfs(x, y+, k-, )) % MOD;
}
return res;
}
int getNumber(vector <int> P, int K) {
n = (int)P.size();
this->K = K;
memset(dp, -, sizeof dp);
for (int i = ; i < n; i++) {
l[i] = r[i] = i;
while (l[i] - >= && P[l[i]-] <= P[i]) l[i]--;
while (r[i]+ < n && P[r[i]+] <= P[i]) r[i]++;
}
return dfs(, , K, );
}
};

代码:

TC SRM 605的更多相关文章

  1. TC srm 673 300 div1

    TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...

  2. TC SRM 597 DEV2

    第一次玩TC的SRM,只完成了一题,有点失落,不过还是要把每个问题都研究清楚才是我的本性,呵呵 第一题思路: 任意一个数,不断除掉2以后的剩下的数若相同则YES否则NO 第二题: 最开始判断字母个数是 ...

  3. TopCoder SRM 605 DIV1

    604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...

  4. TC SRM 663 div2 B AABB 逆推

    AABB Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description One day, Jamie noticed that many En ...

  5. TC SRM 663 div2 A ChessFloor 暴力

    ChessFloor Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description Samantha is renovating a squa ...

  6. TC SRM 665 DIV2 A LuckyXor 暴力

    LuckyXorTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description A lucky number is a positive int ...

  7. Topcoder SRM 605 div1 题解

    日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...

  8. TC SRM 593 DIV1 250

    我只能说的亏没做,要不就挂0了.. 本来想四色定理,肯定4就可以的...然后准备爆,发现3的时候不好爆,又想了老一会,嗯,数据范围不小,应该不是暴力,直接找规律,貌似最大就是3,有一个3连块,输出3, ...

  9. TC SRM 593 DIV2 1000

    很棒的DP,不过没想出,看题解了..思维很重要. #include <iostream> #include <cstdio> #include <cstring> ...

随机推荐

  1. Eclispe使用Maven添加官方库的jar包

    先到百度或google搜索maven仓库,在仓库中搜索需要的jar包,如poi.jar. 搜索到之后找到需要的jar包,找到这里

  2. Reveal 配置与使用

    http://www.th7.cn/Program/IOS/201608/939231.shtml http://www.jianshu.com/p/abac941c2e8e 这个比较好.http:/ ...

  3. php读取html并截取字符串

    一般php采集代码能用的到,这里只是简单的实现代码. <?php $title='脚本学堂'; $hello='jbxue.com!'; $file=file_get_contents('htt ...

  4. CentOS中查看物理CPU信息的方法

    1.概念 [1]物理CPU:实际Server中插槽上的CPU个数.物理cpu数量:可以数不重复的 physical id 有几个.[2]逻辑CPULinux用户对 /proc/cpuinfo 这个文件 ...

  5. c++ 进程权限的提升

    //提升权限 void CManageProcessDlg::DebugPrivilege() {  HANDLE hToken = NULL;  //打开当前进程的访问令牌  int hRet = ...

  6. 打包python脚本为exe可执行文件-pyinstaller和cx_freeze示例

    本文介绍使用cx_freeze和pyinstaller打包python脚本为exe文件 cx_freeze的使用实例 需要使用到的文件wxapp.py, read_file.py, setup.py ...

  7. [MVC] - 异步调用后台的常用方法。

    1. 直接调用Action @Html.Action("GetTopArticle", "Home") 2. 通过url, 并用Jquery异步加载. < ...

  8. 部署图 Deployment Diagram

    UML部署图描述了一个运行时的硬件结点,以及在这些结点上运行的软件组件的静态视图. 部署图显示了系统的硬件,安装在硬件上的软件,以及用于连接异构的机器之间的中间件. 下面这张图介绍了部署图的基本内容: ...

  9. C# ASP.NET系统缓存全解析

    原文:http://blog.csdn.net/wyxhd2008/article/details/8076105 目录(?)[-] 系统缓存的概述 页面输出缓存 页面局部缓存 文件缓存依赖 数据库缓 ...

  10. 手写SqlHelper

    SqlHelper是一个基于.NET Framework的数据库操作组件.组件中包含数据库操作方法,SqlHelper有很多版本,主要以微软一开始发布的SqlHelper类,后面包含进了Enterpr ...