ICPC2017沈阳

orz hhw posted @ 2017年11月23日 18:48 in 做题记录 with tags ACM 解题报告 , 160 阅读

A - BBP Forluma

还没看

B - Bridge

在一个$2*n$的网格上$m$次加边或删边,并询问割边数量。$n,m\leq200000$。

C - Empty Convex Polygons

求$n$个点的最大空凸包。$n\leq50$。

枚举最下面一个点,可以对上面的点进行极角排序,那么可以用一个DP来做,$f[i][j]$表示当前点是$i$,上一个点是$j$的最大面积,再枚举下一个点,判断是否合法即可。注意边界情况的判断,因为点可以再边上。时间复杂度$O(n^4)$。不是我写的,有空写一发$n^3$的。

D - Defense of the Ancients

没看

E - Five-round Show Hand

德州扑克,有空写一发

F - Heron and His Triangle

$T$次让你找到面积比$n$大的边长为$t-1,t,t+1$且面积为整数的最小的三角形。$T\leq30000,n\leq10^{30}$

找规律发现$f_1=4,f_2=14,f_n=4f_{n-1}-f_{n-2}$,然后写个JAVA就好了

G - Infinite Fraction Path

没看

H - Legends of the Three Kingdoms

四个人玩三国杀,起始血量分别为$h_1,h_2,h_3,h_4$,轮流选择一个人让他血量$-1$,每个人都会选择让他胜率最高的决定,如果有多个选择将随机选择,血量为$0$死亡。求主公、内奸、反贼获胜的概率,$h_1,h_2,h_3,h_4<40$

直接四维DP即可,大力讨论一下,卡空间

I - Little Boxes

求四个数的和

J - New Self-describing Sequence

$a_1=1,a_n=a_{n-1}+G(a_{n-1})$,$G(x)$表示$x$的数位和,$s_n=\sum_{i=1}^na_i$。$T$次询问$a_n$和$s_n$,$n\leq10^{17}$,$T\leq32768$。神题

K - Rabbits

$n$个兔子在数轴上排成一列,每次选择最左边或最右边的兔子跳到中间的一个空格位置,问最多能跳多少次。$n\leq500$

很明显除了第一次得跳过很多空格,否则每个空格都利用,答案即$a_n-a_1-min(a_2-a_1,a_n-a_{n-1})-(n-2)$

L - Tree

给一颗$n$个点的无根树染$k$种颜色,问最多能有多少条边满足其两端每种颜色都有出现。

很显然如果删掉这条边后两个联通块都$>=k$那么这条边就可以,DFS一遍就好了。

#include<bits/stdc++.h>
#define N 222222
using namespace std;
int T,n,k,i,x,y,an,tot,fir[N],ne[N*2],la[N*2],sz[N];
void ins(int x,int y){la[++tot]=y;ne[tot]=fir[x];fir[x]=tot;}
void dfs(int x,int fa){
	sz[x]=1;
	for(int i=fir[x];i;i=ne[i])if(la[i]!=fa){
		dfs(la[i],x);
		sz[x]+=sz[la[i]];
	}
	if(min(sz[x],n-sz[x])>=k)an++;
}
int main(){
	for(scanf("%d",&T);T--;){
		scanf("%d%d",&n,&k);an=0;
		for(i=1;i<n;i++)scanf("%d%d",&x,&y),ins(x,y),ins(y,x);
		dfs(1,0);
		printf("%d\n",an);
		for(i=1;i<=n;i++)fir[i]=sz[i]=0;tot=0;
	}
}

M - Wandering Robots

有一个$N*N$的网格图,$K$个障碍点,每次随机游走或者停留(即最多5种选择,随机选一种),问能无穷步之后停留在斜上角的概率。$N\leq10000,K\leq1000$。

先让所有点走的概率都相同,然后随便走一步,状态就稳定了,走到每个点的概率就是其度数,那么对于障碍点修改一下周围点的度数,处理一下答案就好了,用map方便很多。

#include<bits/stdc++.h>
#define N 11111
#define LL long long
using namespace std;
int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
int T,n,k,x,y,i,j,ca,X[N],Y[N];
LL up,all,o;
map<int,int>mp[N];
int G(int x,int y){
	if((x==0||x==n-1)&&(y==0||y==n-1))return 3;
	if(x==0||x==n-1||y==0||y==n-1)return 4;
	return 5;
}
int main(){
	for(scanf("%d",&T);T--;){
		ca++;
		scanf("%d%d",&n,&k);
		all=5ll*(n-2)*(n-2)+4ll*(n-2)*4+3*4;
		up=8ll*(n-2)+3*3+5ll*(n-2)*(n-1)/2;

		for(i=1;i<=k;i++){
			scanf("%d%d",&x,&y);
			if(x+y>=n-1)up-=G(x,y);
			all-=G(x,y);

			mp[x][y]=ca;
			X[i]=x;Y[i]=y;
		}

		for(i=1;i<=k;i++){
			for(j=0;j<4;j++){
				x=X[i]+dx[j];y=Y[i]+dy[j];
				if(x>=0&&x<=n-1&&y>=0&&y<=n-1){
					if(mp[x][y]!=ca){
						all--;
						if(x+y>=n-1)up--;
					}
				}
			}
		}
		printf("Case #%d: ",ca);
		if(n==1)puts("1/1");else{
			o=__gcd(all,up);
			all/=o;up/=o;
			printf("%lld/%lld\n",up,all);
		}
	}
}