您的位置:首页 > 产品设计 > UI/UE

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: