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. 利用rsyslog 对linux 操作进行审计

    环境:客户端和服务端都需要安装rsyslog服务 rsyslog  server端 cd /etc/rsyslog.d/ cat server.conf $ModLoad imtcp $InputTC ...

  2. mysql mmm高可用架构设计

    项目概述:搭建主从,双主,安装Perl模块  安装配置mmm软件  测试 硬件环境:4台虚拟PC 软件环境:rehl6.5 MySQL-5.6.26 percona-xtrabackup-2.3.4 ...

  3. MySQL事务机制

    事务机制的特性通常被概括为"ACID原则" A(Atomic) 原子性: 构成一个事务的所有语句应该是一个独立的逻辑单元,要么全部执行成功, 要么一个都不成功, 你不能只执行他们当 ...

  4. Gulp vs Grunt 前端构建工具对比

    Gulp vs Grunt 前端工程的构建工具对比 1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Jav ...

  5. MongoDB与php的配合使用 【windows版】

    通过学习了如何使用和部署MongoDB,尝试了一下如何将mongodb应用到php的程式中去. 1.预备工作 首先得准备好mongodb,并按照相关方法部署以及服务能正常运行中. 对于初学者,可以参考 ...

  6. Sending Email from mailx Command in Linux Using Gmail’s SMTP

    The mailx or mail command in Linux is still providing service for guys like me, especially when we n ...

  7. SQL中的日期时间函数

    之所以把日期时间函数单独拿出来回顾一下,是因为这一部分的内容比较独立,C#中也有类似的日期时间函数,趁着想得起来,写个标题先.

  8. 第一个C#应用 【搜索软件】

    搜索软件V1.0 [附软件截图][http://pan.baidu.com/s/1mihEbe4] 设备搜索:支持广播搜索[local search],指定ip[range search]搜索,直接w ...

  9. MySQL 库大小、表大小、索引大小查询命令

    1.进去指定schema 数据库(存放了其他的数据库的信息)     mysql> use information_schema; 2.查询所有数据的大小      mysql> sele ...

  10. sysfs->sys简单介绍

    Sys节点 1:sysfs 是 Linux 内核中设计较新的一种虚拟的基于内存的文件系统, sysfs 的挂载点 /sys 目录结构. 2:/sys 文件系统下的目录结构 /sys 下的目录结构是经过 ...