Codeforces Round #328 (Div. 2)

A. PawnChess

白棋跟黑棋只能往上或往下走,如果有阻碍就无法通过

w到第一行的最小距离是s1

b到最后一行的距离是s2

s1 <= s2,那就是输出A

否则输出B

<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
char s[10][10];
int vw[10], vb[10];
int main()
{
	memset(vw, 0, sizeof(vw));
	memset(vb, 0, sizeof(vb));
	int answ = 0, ansb = 0;
	for(int i = 0; i < 8; i++)
	{
		scanf("%s", s[i]);
		for(int j = 0; j < 8; j++)
		{
			if(s[i][j] == 'B') vw[j] = 1;
			if(s[i][j] == 'W' && vw[j] == 0 && answ == 0) answ = i; 
		}
	}
	for(int i = 7; i >= 0; i--)
	{
		for(int j = 0; j < 8; j++)
		{
			if(s[i][j] == 'W') vb[j] = 1;
			if(s[i][j] == 'B' && vb[j] == 0)
			{
				ansb=7-i;
				break;
			}
		}
		if(ansb > 0) break;
	}
	if(answ <= ansb) printf("A\n");
	else printf("B\n");
	return 0;
} </span>

B. The Monster and the Squirrel

正n变形,顶点顺时针标记为1~n,从1开始画对角线,如果在画一条对角线时要跟另一条对角线交叉,那么就不要延伸出去,与另一条对角线相交于一点就好

问你在这个正n变形里面有几块空间

通过画图找规律可以知道是(n-2)*(n-2)

C. The Big Race

W跟B这两个人走一步分别能走出w米跟b米

举个例子w=2,b=3,总长度l=7

当W走了3步到达6时,再走一步就要到8,>7,所以W最多走了6米

同理B最多也是走了6米

所以l=6是平局

求1<=x<=t中,平局的概率

用最简式表示

这实际上就是求w跟b的公倍数

公倍数~公倍数+min(w,b)这一段书都是可以的

还有一段就是1~min(w,b)

然后考虑临界点

<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
#define ll __int64
ll gcd(ll a, ll b)
{
	ll res = 1;
	while(res)
	{
		res = a%b;
		a = b;
		b = res;
	}
	return a;
}
int main()
{
	ll t, w, b;
	scanf("%I64d%I64d%I64d", &t, &w, &b);
	ll ai = min(w, b);
	ll ans;
	if(t < ai) ans = t;
	else
	{
		ans = ai - 1;  
		ll bi = max(w, b);
		ll G = gcd(w, b);
		ll lo = w/G;
		int s1 = 0, s2 = 0;
		while(lo)
		{
			lo /= 10;
			s1++;
		}
		lo = b;
		while(lo)
		{
			lo /= 10;
			s2++;
		}
		if(s1+s2 < 20 )
		{
			G = w/G*b;
			ll p = t/G*G+ai;
			if(p <= t) ans = ans + t/G*ai;
			else ans = ans + (t/G-1)*ai + t - t/G*G + 1;
		}
	}
	
	ll f = gcd(ans, t);
	printf("%I64d/%I64d\n", ans/f, t/f);
	return 0;
} </span>

D. Super M

树形dp

n个顶点,n-1条双向边

m个点是超人必须要去的点

问从m个点中任选一个点为起点,遍历所有的点最短的路程是多少

输出起点和路程,如果路程相同的起点有多个,输出数值最小的那个

m个点肯定是连成一棵树的,我们可以从第一个点开始,搜索

记录每个顶点到第一个点的距离,找出到第一个点距离最长的那个点,这个点就是这棵树的终点

从终点开始搜索,记录与终点距离最长的那个点以及距离sx

最终的最短的距离 = 这棵树的边数*2 - sx

最后还需要进一步确认记录的点数值是否是最小的

#include <bits/stdc++.h>
using namespace std;
#define inf 130000
vector<int>adj[inf];
int vis[inf];
int sizee[inf], dis[inf];

void dfs(int p, int u)
{
	sizee[u] = 0;
	if(vis[u]) sizee[u]=1;
	for(int i = 0; i < adj[u].size(); i++)
	{
		int v = adj[u][i];
		if(v!=p)
		{
			dis[v] = dis[u] + 1;
			dfs(u, v);
			sizee[u] += sizee[v];
		}
	}	
}
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1; i < n; i++)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);		
	}
	memset(vis, 0, sizeof(vis));
	for(int i = 0; i < m; i++)
	{
		int a;
		scanf("%d", &a);
		vis[a] = 1;
	}
	memset(dis, 0, sizeof(dis));
	dfs(-1, 1);
	int v = -1;
	for(int i = 1; i <= n; i++)
	{
		if(vis[i] && (v==-1 || dis[i] > dis[v])) v = i;
	}
	memset(dis, 0, sizeof(dis));
	dfs(-1, v);
	int sum = 0, sx = 0;
	for(int i = 1; i <= n; i++)
	{
		if(sizee[i] && m-sizee[i]>0) sum += 2;
		if(vis[i]) sx = max(sx, dis[i]);
	}
	for(int i = 1; i <= n; i++)
	{
		if(sx==dis[i] && vis[i] && i<v) v = i; 
	}
	printf("%d\n%d\n", v, sum-sx);
	return 0;
} 


E. BCPC

这一题就是求满足以下条件的有多少组

1、(r[i] - c) * (w[j] - d) > r(r[j] - c) * (w[i] - d)

2、(r[j] - c) * (w[k] - d) > r(r[k] - c) * (w[j] - d)

3、(r[k] - c) * (w[i] - d) > r(r[i] - c) * (w[k] - d)

(以下的r[ ]代表的就是减去c后的,w[ ]代表减去d后的)

r[i] * w[j] > r[j] * w[i]   =>  r[i]/w[i] 和 r[j]/w[j]的大小关系 => 显然这大小关系跟w[ ]的正负有关

令x[i] = r[i]/w[i],接下来就是对w[ ]分类讨论

    w[i]   w[j]   w[k]

1、+      +       +

相应的x[ ]的大小就是xi > xj > xk > xi,显然不成立

2、-      -        -

相应的x[ ]就是xi > xj > xk > xi,也不成立

3、+    +       -

能得到xi > xj && xj < xk && xk < xi,也就是xi > xk > xj

4、+    -       -

得到xi < xj && xj > xk && xk <xi,也就是xj > xi > xk

根据上面的分类讨论,我们可以将wi分为正负分别放入两个容器里面  po放的是正的,ne放的是负的

还有一点要注意的就是w == 0的时候

通过简单的推理,我们可以知道对于第3种情况,只可能是xi对应的w=0,此时的r<0

第四种情况只能是xj对应的w=0,r>0

<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
#define inf 345678+10
#define ll __int64
vector<double>po, ne;
int r[inf], w[inf];
double p[inf]; 

int main()
{
	int n, c, d;
	scanf("%d%d%d", &n, &c, &d);
	for(int i = 1; i <= n; i++)
	{
		scanf("%d%d", &r[i], &w[i]);
		r[i] -= c, w[i] -= d;
		p[i] = r[i]*1.0/w[i];
	}	
	for(int i = 1; i <= n; i++)
	{
		if(w[i] > 0) po.push_back(p[i]);
		else if(w[i] < 0) ne.push_back(p[i]);
	}
	
	sort(po.begin(), po.end());
	sort(ne.begin(), ne.end());
	
	ll f = 0, s = 0;
	for(int i = 0; i < po.size(); i++)
	{
		f += (lower_bound(ne.begin(), ne.end(), po[i]) - ne.begin());
	}
	for(int i = 0; i < ne.size() ;i++)
	{
		s += (lower_bound(po.begin(), po.end(), ne[i]) - po.begin());
	}
	
	ll ans = 0;
	for(int i = 1; i <= n; i++)
	{
		if(w[i] > 0)
		{
			ans += (ll)(ne.end()-upper_bound(ne.begin(),ne.end(),p[i])) * (lower_bound(ne.begin(),ne.end(),p[i])-ne.begin());
		}
		else if(w[i] < 0)
		{
			ans += (ll)(po.end()-upper_bound(po.begin(),po.end(),p[i])) * (lower_bound(po.begin(),po.end(),p[i])-po.begin());
		}
		else
		{
			if(r[i] < 0) ans += f;
			else ans += s;
		}
	}
	printf("%I64d\n", ans);
	return 0;
} </span>


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值