Good Bye 2015 (One University One Question) Round III
2016-02-07 13:58
501 查看
A. Red packet
题意:n个人分m元的红包,然后告诉你k个人获得的红包大小,问你如果你想成为手气王(钱拿的最多),至少需要得到多大的红包,或者输出”Impossible”,如果不可能的话,注意红包必须分完,并且每个人获得的红包大小都是整数(>0)
分析:
首先可以得到k个人里的最大值M,设现在剩下的钱是R,那么首先要成为手气王,就必须得到至少M+1,但是最多是R−(n−k−1), 那么接下来其实就可以二分来处理了,假设现在的答案是mid,考虑如果在那n−k−1人里有人同样得到了mid元,即不等式2⋅mid+n−k−2≤R,那么mid这个答案是非法的,否则就是合法的,如此就可以二分 得到最小的答案了,注意特判k=n−1的情况,因为红包必须分完。
B. Coloring
题意:给出一个n⋅m 的二维格子,要求使用不超过k种的颜色进行染色,其中要求,曼哈顿距离为奇数的格子不能使用相同的颜色,求方案数,Mod 109+7
分析:
首先对格子进行黑白染色,那么任意一对黑白格子之间的距离都是奇数,所以染黑色格子的颜色和染白色格子的颜色不能相同。
解法1:
先dp预处理,dp[i][j]表示刚好用i种颜色,染完j个格子的方案数
dp[i][j]=ij−C(i,i−1)⋅dp[i−1][j]−C(i,i−2)⋅dp[i−2][j]−...−C(i,1)⋅dp[1][j]
然后对于给定的n,m,k,计算出黑白格子的数目,然后枚举一共使用多少种颜色(设为i),再枚举使用多少种颜色给黑格子染色(设为j),答案就是C(k,i)⋅C(i,j)⋅dp[j][black]⋅dp[i−j][white]
时间复杂度O(T⋅k2)
解法2:
其实和解法1是类似的,同样也是对于给定的 n,m,k,计算出黑白格子数目,枚举一共使用多少种颜色(设为i),再枚举使用多少种颜色给黑格子染色(设为j),根据容斥原理,此时使用j 种颜色给黑格子染色的方案数为:
C(j,j)⋅jblack−C(j,j−1)⋅(j−1)black+C(j,j−2)⋅(j−2)black−...+(−1)j−1⋅C(j,1)
同理可以算出此时使用i−j 种颜色对白格子染色的方案数,二者相乘再乘上C(k,i)就是此时的答案,累加即可。
C. String in the tree
题意:给定一棵树,树上每个结点都是一个小写字母
从1出发到n个结点有n条简单路径,每条路径求出所构成的字符串的不同子串数目
分析:
如果我们能对一个字符串,结尾进行添加删除,并且查询子串,那么树这个条件就没有卵用了,主要从树根dfs下去,到某一结点就相当于在结尾添加字符,递归回去的时候就相当于删除字符。
解法:
通过上面的分析问题就转化为如何在一个字符串末尾添加删除字符,并且能统计子串数目。
回忆一下用后缀数组处理这个问题的统计方法为∑n1n−sa[i]−lcp(sa[i],sa[i−1])
那么把字符串逆过来,删除和添加就是在头部添加,这样的话,每次添加删除就相当于添加删除一个后缀串,如果能快速找到这个后缀串的sa,只要在插入删除的时候和前面后面串简单计算一下,维护一个子串数目就可以了。
这步可以用一个set来进行维护,那么如何比较两个串的字典序大小呢,只要把字符串进行hash,两个串比较一下LCP之后第一个字符就可以了。
时间复杂度为O(nlog2(n))
D. Ancient battle tree
题意:给出一颗无权树,求最远点对数目。
分析:
非常抱歉题目没有讲清楚,点对(a,b)中a可以等于b
暂时没有标程的解法,下面讲下我自己的做法。
首先通过两次bfs求出直径长度D。
接下来考虑深搜这棵树(计算某个结点时,相当于考虑这个结点作为某个最远点对的LCA),假设在处理某个以u为根的子树,u的儿子已经全部处理好,我们需要知道u的每个儿子的子树里深度最大的叶子节点深度和对应数量,然后同时可以把这个信息更新给u, 接下来依次枚举u的每个儿子,假设现在处理v, 设v 这个子树里距离v最远的点的深度为d,数量为c,设u深度为du,则现在要找深度为D−(d−du)+du的点,而每当我们处理好一个儿子,就把距离它最远的点的深度以及数目存起来了,因此此时我就可以得到深度为D−(d−du)+du的点的数目,每次累加即可,注意需要清空答案。另外n=1答案是1。。。
#include <iostream> #include <fstream> #include <cstring> #include <climits> #include <deque> #include <cmath> #include <queue> #include <stack> #include <list> #include <map> #include <set> #include <utility> #include <sstream> #include <complex> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include <ctime> #include <bitset> #include <functional> #include <algorithm> using namespace std; const int N = 200010; int deep ; int tar ; int cnt ; int head ; int tot; bool vis ; int dist ; struct Edge { int next; int to; }edge[N << 1]; int end_p; void addedge(int from, int to){ edge[tot].to = to; edge[tot].next = head[from]; head[from] = tot++; } int bfs(int s) { queue <int> qu; memset(vis, 0, sizeof(vis)); memset(dist, 0x3f3f3f3f, sizeof(dist)); int d = 0; qu.push(s); dist[s] = 0; vis[s] = 1; while (!qu.empty()) { int u = qu.front(); qu.pop(); for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (!vis[v]) { vis[v] = 1; qu.push(v); dist[v] = dist[u] + 1; if (d < dist[v]) { d = dist[v]; end_p = v; } } } } return d; } long long ans = 0; int max_d; int use ; int cases = 0; void dfs(int u, int fa, int d) { deep[u] = d; bool flag = 0; tar[u] = -1; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa) { continue; } flag = 1; dfs(v, u, d + 1); tar[u] = max(tar[u], tar[v]); } if (!flag) { cnt[u] = 1; // leaf node tar[u] = deep[u]; return; } for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa) { continue; } if (tar[u] == tar[v]) { cnt[u] += cnt[v]; } int res = max_d - (tar[v] - deep[u]); if (res == 0) { ans += cnt[tar[v]]; } else { ans += (long long)use[deep[u] + res] * cnt[v]; } use[tar[v]] += cnt[v]; } for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa) { continue; } use[tar[v]] = 0; } } int main() { int n, u, v; while (~scanf("%d", &n)) { ++cases; if (n == 1) { printf("1\n"); continue; } memset(head, -1, sizeof(head)); memset(cnt, 0, sizeof(cnt)); tot = 0; memset(use, 0, sizeof(use)); for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } bfs(1); max_d = bfs(end_p); ans = 0; if (max_d == n - 1) { printf("1\n"); continue; } dfs(1, -1, 1); printf("%lld\n", ans); } return 0; }
相关文章推荐
- spoj 375 Query on a tree(树链剖分,线段树)
- linq中AsEnumerable和AsQueryable的区别
- iOS应用开发中视图控件UIWindow的基本使用教程
- mongoose 文档(四) queries
- Flash Builder4.7安装
- 春节与UI
- 16 SequenceInputStream、PrintStream、Properties、递归、编码
- arduino 声波
- LeetCode60. Permutation Sequence
- HDU 2894 DeBruijin(欧拉回路)
- UITableView上的批量操作(系统方法)
- easyui-datagrid 的loader属性用法
- 导航控制器 UINavigationController
- Hibernate中inverse="true"的理解
- [翻译]The Neophyte's Guide to Scala Part 12: Type Classes
- 0206-UITableView上的批量操作(自定义)
- Arduino Nano + WIZ550io = 简易上网
- 百思学习笔记08-封装UIBarButtonItem的创建
- Android Wear Develope Guide 1
- UITableView UITableViewCell UITableViewController