A  Average Score http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5373

a班有n个人,b班有m个人,bob在a班,现在知道除了bob以外的所有人的成绩,还知道bob如果从a班转到b班,两个班的平均成绩都会提高,问bob合法的成绩区间。

解法,求一下两个班的平均成绩,bob的成绩肯定要比a班的小,比b班的大。

 #include<cstdio>
int main(){
int t,n,m,x,sa,sb;
while(~scanf("%d",&t)){
while(t--){
scanf("%d%d",&n,&m);
sa=sb=;
n--;
for(int i=;i<n;i++){
scanf("%d",&x);
sa+=x;
}
for(int i=;i<m;i++){
scanf("%d",&x);
sb+=x;
}
sb/=m;
sb++;
if(sa%n==){
sa/=n;
sa--;
}
else{
sa/=n;
}
printf("%d %d\n",sb,sa);
}
}
return ;
}

B Building Fire Stations http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5374

输入n个点,n-1条边,构成一颗树,选树上两个点作为消防队,使得n个点中距离消防队最远的值最小。

解法,如果是选一个点,那必然是选树的直径(树上最长链,距离最远的两个点之间的路径)的中点,这样到达树上所有点最远的距离肯定最小。当选两个点,我猜想两个点都在直径上选,然后二分答案,判断合法的时候一个消防队从直径的头部加上mid,一个从直径的尾部减去mid,然后判断能否覆盖所有点,二分答案logn,判断on,总复杂度nlogn。

网上对于猜想的证明:

先给出这个问题的数学描述:
给定一棵无根树 T 。定义以 T 上一对点 (a, b) 为“复根”的树的高度 h(a, b) = max min(dist(x, a), dist(x, b)), for all x on T 。现求 H(T) = min h(a, b), for all (a, b) available 。

我们先讨论一下 H(T) 的上界。
引理 1 对任意的一棵树 T ,不妨设其直径长为 d ,有 H(T) <= [d / 2] ([x] 意为对 x 向下取整)。
证明 当 d 为偶数时,T 有且只有一个中心点 x 。取中心点为“复根”,显然 h(x, x) = d / 2 = [d / 2] 。当 d 为奇数时, T 有且只有一条中心边,不妨设其端点分别为 x 和 y 。则显然 h(x, y) = (d - 1) / 2 = [d / 2] 。证毕。

根据引理 1 ,我们可知 H(T) 的可达上界是 [d / 2] 。所以我们接下来的目标就是找是否存在比 [d / 2] 更小的方案。下面我们证明另一个结论。
引理 2 对树 T 上任一对点 (a, b) ,若 h(a, b) < [d / 2] ,则 a 到 b 的路径上一定经过 T 的中心点(边)。
证明 反证法可证。此证明不难,留给读者。

引理 3 对树 T 上任一对点 (a, b) ,若 h(a, b) < [d / 2] ,则对 T 的任一条直径 D ,不妨设距离 a 较近的点为 l ,有 dist(b, l) > [d / 2] 且 dist(a, l) < [d / 2];另一端点 r 距离 b 较近,有 dist(b, r) < [d / 2] 且 dist(a, r) > [d / 2] 。
证明 由引理 2 可以直接推出该引理。此证明不难,留给读者。

引理 4 对任意的 (a, b) ,若其中存在至少一个点不在树 T 的某一条直径上,且 h(a, b) < [d / 2] 。则存在一对点 (a', b') ,其中 a' 和 b' 都在树 T 的任一条直径上,使得 h(a', b') <= h(a, b) 。
证明 对任意满足条件的 (a, b) ,不妨设其中 b 不在 T 的一条直径 D 上。记:
x: 直径 D 上距离 b 最近的点为 x 。
T': 将 T 上 D 包含的边都从边集中去掉得到一个森林 G ,其中 x 所在的树记为 T' 。
y: 在 T' 上 x 的最远点记为 y 。
l, r: 由于 h(a, b) < [d / 2] ,故 D 的两个端点中记距离 a 较近的点为 l ,另一端点记为 r 。接下来证明 h(a, x) <= h(a, b) :
根 据以上条件,显然有:dist(x, r) < dist(b, r) < [d / 2] 。进而可得 x 到 r 的路径上不经过 T 的中心点(边)。于是可知 dist(x, r) >= dist(x, y) (否则 r 就不可能在直径上)。
1) 因为 h(a, b) >= min(dist(a, r), dist(b, r)) = dist(b, r) > dist(x, r) >= dist(x, y) ,且 y 是 T' 中 x 的最远点。所以对 T' 中的任一点 k ,都有 dist(x, k) <= dist(x, y) <= h(a, b) ,故 min(dist(a, k), dist(x, k)) <= h(a, b) 。
2) 而对于所有不在 T' 中的点 k ,都有 dist(x, k) <= dist(b, k) ,故 min(dist(a, k), dist(x, k)) <= min(dist(a, k), dist(b, k)) <= h(a, b) 。
结合 1) 和 2) 可得:对 T 中任一点 k , 都有 min(dist(a, k), dist(x, k)) <= h(a, b) 。故 h(a, x) <= h(a, b) 。
所以我们找到了一对点 (a, x) ,满足 h(a, x) <= h(a, b) 。证毕。

于是我们得到了下面这个最关键的结论:
定理 对树 T 上任一对点 (a, b) ,若 h(a, b) = H(T) ,则对 T 的任一条直径 D , a 和 b 都在 D 上。
证明 由引理 3 可知,不存在一种有一个点不在直径上的最优解。故该定理得证。

所以我们只要枚举所有两个点都在直径上的方案就可以找到一组最优解。于是我们就转化为一个一维的问题。可以二分答案,然后 O(N) 的判定可行性。总体复杂度是 O(NlogN) 。

spfa版本

 //#define debug
//#define txtout
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const double eps=1e-;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int M=2e5+; class Spfa { ///最短路快速算法 O(E*k)(k~=2)
typedef int typec;///边权的类型
static const int ME=4e5+;///边的个数
static const int MV=2e5+;///点的个数
struct E {
int v,next;
typec w;
} e[ME];
int n,le,head[MV],inque[MV],pre[MV],i,u,v;
typec dist[MV];
bool used[MV];
queue<int> q;
public:
void init(int tn) { ///传入点的个数
n=tn;
le=;
for(i=; i<=n; i++) head[i]=-;
}
void add(int u,int v,typec w) {
e[le].v=v;
e[le].w=w;
e[le].next=head[u];
head[u]=le++;
}
bool solve(int s) { ///传入起点,存在负环返回false
for(i=; i<=n; i++) {
dist[i]=inf;
used[i]=true;
inque[i]=;
pre[i]=-;
}
used[s]=false;
dist[s]=;
inque[s]++;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty()) {
u=q.front();
q.pop();
used[u]=true;
for(i=head[u]; ~i; i=e[i].next) {
v=e[i].v;
if(dist[v]>dist[u]+e[i].w) {
dist[v]=dist[u]+e[i].w;
pre[v]=u;
if(!used[v]) continue;
used[v]=false;
q.push(v);
inque[v]++;
if(inque[v]>n) return false;
}
}
}
return true;
}
typec getdist(int id) {
return dist[id];
}
int getpre(int id) {
return pre[id];
}
} g;
int getfar(int n){
int res=;
for(int i=;i<=n;i++){
if(g.getdist(i)>g.getdist(res)){
res=i;
}
}
return res;
}
vector<int> zhi;
int lz;
bool cover[M];
bool judge(int n,int d,int &x,int &y){
int lid=min(d,lz-);
int rid=max(lid+,lz--d);
x=zhi[lid];
y=zhi[rid];
g.solve(x);
for(int i=;i<=n;i++){
cover[i]=false;
}
bool ok=true;
for(int i=;i<=n;i++){
if(g.getdist(i)<=d){
cover[i]=true;
}
else{
ok=false;
}
}
if(ok) return true;
g.solve(y);
for(int i=;i<=n;i++){
if(cover[i]) continue;
if(g.getdist(i)>d) return false;
}
return true;
}
int main() {
#ifdef txtout
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t,n,u,v;
while(~scanf("%d",&t)) {
while(t--){
scanf("%d",&n);
g.init(n);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
g.add(u,v,);
g.add(v,u,);
}
g.solve();
int z1=getfar(n);
g.solve(z1);
int z2=getfar(n);
zhi.clear();
int now=z2;
while(true){
zhi.push_back(now);
if(now==z1) break;
now=g.getpre(now);
}
lz=zhi.size();
int L=,R=lz,ans=lz,x,y,ax,ay;
while(L<=R){
int mid=(L+R)>>;
if(judge(n,mid,x,y)){
R=mid-;
if(ans>mid){
ans=mid;
ax=x;
ay=y;
}
}
else{
L=mid+;
}
}
printf("%d %d %d\n",ans,ax,ay);
}
}
return ;
}

C Card Game http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3821

放放放,跳过。

D Domination http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5376

输入n,m表示棋盘有n行m列,人每天会随机找一个空的格子放棋子,问覆盖棋盘的天数的期望。覆盖的定义是棋盘的每一行至少有一个棋子,每一列至少有一个棋子。

解法:E=x1*p1+x2*p2+...

也就是我们需要求出1天覆盖棋盘的概率p1,2天覆盖棋盘的概率p2,。。。最后1*p1+2*p2+3*p3...

如何求p1到pn。如果暴力,第一天有n*m种选法,每种的概率是1/(n*m),以此类推,级别是n!

不难发现第一天选11,第二天选22,和第一天选22,第二天选11都是两天覆盖了2*2的棋盘,也就是状态是重复的。

定义dp【n】【m】【k】表示覆盖n*m的棋盘花费k天的概率。

当前状态是dp【i】【j】【k】,则下一步可以推向几个状态

定义sum=n*m,即棋盘的总点数

一是

选的点不在未覆盖的行上,也不在未覆盖的列上,此时下一个状态就是dp【i】【j】【k+1】,因为是随机放,概率就等于满足条件的个数除以可选的总数(i*j-k)/(sum-k)

同理,选的点还有3种情况,只贡献一行,只贡献一列,贡献一行一列,分别转移。

加入dp==0 continue可以减掉许多达不到的状态优化近10倍

 #include<cstdio>
const double eps=1e-;
const int M=;
double dp[M][M][M*M];
int main(){
int t,n,m;
while(~scanf("%d",&t)){
while(t--){
scanf("%d%d",&n,&m);
int all=n*m;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
for(int k=;k<=all;k++){
dp[i][j][k]=;
}
}
}
dp[][][]=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
for(int k=;k<=all;k++){
if(dp[i][j][k]<eps) continue;
if(i!=n||j!=m)
dp[i][j][k+]+=dp[i][j][k]*(i*j-k)/(all-k);
dp[i+][j][k+]+=dp[i][j][k]*(n-i)*j/(all-k);
dp[i][j+][k+]+=dp[i][j][k]*i*(m-j)/(all-k);
dp[i+][j+][k+]+=dp[i][j][k]*(n-i)*(m-j)/(all-k);
}
}
}
double ans=;
for(int i=;i<=all;i++){
ans+=i*dp[n][m][i];
}
printf("%.12f\n",ans);
}
}
return ;
}

E Excavator Contest http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5377

某大神的构造。有空来看。

http://blog.csdn.net/u014250021/article/details/40109587

F Fiber-optic Network http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5378

小岛大神的树形dp,容斥。http://www.shuizilong.com/house/archives/2014-acmicpc-asia-mudanjiang-regional-contest-onsite/

http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=2845448

某不知名大神的莫比乌斯

http://blog.csdn.net/u012848726/article/details/46874335

都是需要学习的。

G Garden and Sprinklers http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3825

放放放。跳过。

H Hierarchical Notation http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5380

输入一个串,是一系列键值对,然后输入q组查询,每次查询输入键,要求将对应的值打印出来。键值对由:连接。

解法:首先枚举所有的:,然后:之前的“”就是键,存在map中,map里存pair,表示该字符串的值的头和尾的下标。都处理好后,对每个查询,就在map中拿到它的头尾,然后打印就行了。我没处理a.b.c非法的,能过,说明都是合法的查询,那就直接查最后一个.之后的字符串就可以了。

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
using namespace std;
typedef pair<int,int> pii;
const int M=1e6+;
map<string,pii> mp;
map<string,pii>::iterator it;
string str;
pii p;
char a[M],b[M];
void getstr(int l,int r,char c[]){
str.resize(r-l+);
int ls=;
for(int i=l;i<=r;i++){
str[ls++]=c[i];
}
}
void init(){
mp.clear();
int la=strlen(a);
for(int i=;i<la;i++){
if(a[i]!=':') continue;
for(int j=i-;j>=;j--){
if(a[j]=='"'){
getstr(j,i-,a);
break;
}
}
p.first=i+;
int tmp=;
for(int j=i+;j<la;j++){
if(a[j]=='{'){
tmp++;
continue;
}
if(a[j]=='}'){
if(!tmp){
p.second=j-;
break;
}
tmp--;
if(tmp) continue;
p.second=j;
break;
}
if(a[j]==','&&!tmp){
p.second=j-;
break;
}
}
mp[str]=p;
}
}
int main(){
int t,n;
while(~scanf("%d",&t)){
while(t--){
scanf("%s%d",a,&n);
init();
while(n--){
scanf("%s",b);
int s=,lb=strlen(b);
for(int i=;i<lb;i++){
if(b[i]=='.'){
s=i+;
}
}
getstr(s,lb-,b);
it=mp.find(str);
if(it==mp.end()){
puts("Error!");
continue;
}
p=it->second;
for(int i=p.first;i<=p.second;i++){
putchar(a[i]);
}
puts("");
}
}
}
return ;
}

I Information Entropy http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5381

按照题目的公式求和,注意p==0时是0,最后取相反数。

 #include<cstdio>
#include<cmath>
char a[];
double f(int p,char c){
double res=p*0.01;
if(c=='b') return res*log2(res);
if(c=='n') return res*log(res);
return res*log10(res);
}
int main(){
int t,n,x;
while(~scanf("%d",&t)){
while(t--){
scanf("%d%s",&n,a);
double sum=;
while(n--){
scanf("%d",&x);
if(!x) continue;
sum+=f(x,a[]);
}
printf("%.12f\n",-sum);
}
}
return ;
}

J Jacobi Pattern http://wzimpha-wordpress.stor.sinaapp.com/uploads/2014/11/Jacobi-Pattern.pdf

这种题属于进final的选手思考的。我就暂时放一放。

K Known Notation http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5383

输入一个带数字和*的串,问最少几次操作变成合法逆波兰表达式,操作有两种,一种是插入一个数字或星,一种是交换任意两个字符。

解法:首先12*可以消掉变成2,也就是说两个数字加一个星可以变成一个数字,那么如果一共有n个星,我们至少需要n+1个数字,并且数字尽可能在前面更好,所以第一步贪心的在前面加数字,加到星的个数加1即可。第二步遍历,记录一下前面剩了多少个数字,只要遇到星,就会和前面两个数字抵消成一个数字,相当于前面剩余的数字减1,如果前面剩余的数字不够了,则贪心的选择最后一个数字和当前的星交换位置。

 #include<cstdio>
#include<cstring>
const int M=1e3+;
char a[M];
int main(){
int t;
while(~scanf("%d",&t)){
while(t--){
scanf("%s",a);
int la=strlen(a),star=,num=;
for(int i=;i<la;i++){
if(a[i]=='*'){
star++;
}
}
num=la-star;
int ans=,tmp=;
if(num<star+){
ans=star+-num;
tmp=ans;
}
for(int i=;i<la;i++){
if(a[i]!='*'){
tmp++;
continue;
}
if(tmp>=){
tmp--;
continue;
}
for(int j=la-;j>=;j--){
if(a[j]!='*'){
ans++;
a[j]='*';
tmp++;
break;
}
}
}
printf("%d\n",ans);
}
}
return ;
}

end

2014ACM/ICPC亚洲区牡丹江站 浙大命题的更多相关文章

  1. 2014ACM/ICPC亚洲区西安站 复旦命题

    http://codeforces.com/gym/100548 A 签到 问一个序列是不是yes,yes的序列满足每个数都是3的倍数. #include<cstdio> int main ...

  2. 2014ACM/ICPC亚洲区鞍山站 清华命题

    A http://acm.hdu.edu.cn/showproblem.php?pid=5070 先跳过. B http://acm.hdu.edu.cn/showproblem.php?pid=50 ...

  3. 2014ACM/ICPC亚洲区西安站 F题 color (组合数学,容斥原理)

    题目链接:传送门 题意: n个格子排成一行.我们有m种颜色.能够给这些格子涂色,保证相邻的格子的颜色不同 问,最后恰好使用了k种颜色的方案数. 分析: 看完题目描写叙述之后立刻想到了一个公式 :C(m ...

  4. 2014ACM/ICPC亚洲区西安站现场赛 F color(二项式反演)

    题意:小球排成一排,从m种颜色中选取k种颜色给n个球上色,要求相邻的球的颜色不同,求可行的方案数,答案模1e9+7.T组数据,1<= n, m <= 1e9, 1 <= k < ...

  5. (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...

  6. 2013ACM/ICPC亚洲区南京站现场赛---Poor Warehouse Keeper(贪心)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4803 Problem Description Jenny is a warehouse keeper. ...

  7. HDU 5950 Recursive sequence 【递推+矩阵快速幂】 (2016ACM/ICPC亚洲区沈阳站)

    Recursive sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  8. HDU 5952 Counting Cliques 【DFS+剪枝】 (2016ACM/ICPC亚洲区沈阳站)

    Counting Cliques Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. HDU 5948 Thickest Burger 【模拟】 (2016ACM/ICPC亚洲区沈阳站)

    Thickest Burger Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

随机推荐

  1. php输出utf-8格式

    header("Content-type:text/html;charset=utf-8"); 输出数据前插入以上代码,以utf-8格式输出,避免乱码

  2. Laravel 5 基础(十一)- 子视图和表单复用

    我们需要处理编辑文章的问题.当然我们可以手工添加新的路由,就像这样: Route::get('/articles/{id}/edit', 'ArticleController@edit'); 让我们在 ...

  3. Delphi 2010初体验,是时候抛弃Delphi 7了

    Delphi 2010已于近日由Embarcadero公司发布.作者Kim Madsen作为一名资深的Delphi开发者,在他的博客中谈到了Delphi 2010的新性能.它的使用感受以及对Delph ...

  4. C# 多线程 简单使用方法以及常用参数

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  5. 第七章 管理类型(In .net4.5) 之 使用类型

    1. 概述 本章介绍 值类型的装箱拆箱.类型转换 以及 C#4.0新推出的 dynamic 关键字. 2. 主要内容 2.1 装箱和拆箱 2.2 类型转换 有四种方式可以实现类型转换: ① 隐式转换: ...

  6. Python学习教程(learning Python)--2.3.3 Python函数型参详解

    本节讨论Python下函数型参的预设值问题. Python在设计函数时,可以给型参预设缺省值,当用户调用函数时可以不输入实参.如果用户不想使用缺省预设值则需要给型参一一赋值,可以给某些型参赋值或不按型 ...

  7. poj 2046 Gap

    题目连接 http://poj.org/problem?id=2046 Gap Description Let's play a card game called Gap. You have 28 c ...

  8. 【转】Git常用命令备忘

    Git配置 git config --global user.name "robbin" git config --global user.email "fankai@g ...

  9. Labview实现频率调制(FM)

    Labview实现频率调制(FM) 频率调制的原理: 自己的实现为三角函数分解 根据这个公式在Labview中连线则可以得到最终的波形输出 实现效果 从频域图中可以看出,载波信号的频率被调制,原本为双 ...

  10. 不同系统间传输float型数据

    #include <stdio.h> #include <string.h> int main(void) { union result {          float d; ...