首页 > 代码库 > Codeforces Round #284 (Div. 2)

Codeforces Round #284 (Div. 2)

Problem C

题目大意:一个平面内有一些无限长的直线,把平面分成了若干块,从一块走一步可以走到与它有公共边的另一块,但是只有公共点不能一步走过去。给定两个在块内部的点,问从S点到T点最少走几步。

题目分析:由于每步只能跨越公共边,不能从两直线交点处跨越,所以一步只能越过 S 与 T 之间的一条直线,那么答案就是 S 与 T 之间有多少条直线(即 S 与 T 在这些直线的两侧)。判断 S 与 T 在直线 l 两侧 :  l : ax + by + c = 0        (a*Sx + b*Sy + c) 与 (a*Tx + b*Ty + c) 异号。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int MaxN = 300 + 5;int Sx, Sy, Tx, Ty, n, Ans, a, b, c;typedef long long LL;LL N1, N2;int main() {	scanf("%d%d%d%d", &Sx, &Sy, &Tx, &Ty);	scanf("%d", &n);	Ans = 0;	for (int i = 1; i <= n; ++i) {		scanf("%d%d%d", &a, &b, &c);		N1 = (LL)a * (LL)Sx + (LL)b * (LL)Sy + (LL)c;		N2 = (LL)a * (LL)Tx + (LL)b * (LL)Ty + (LL)c;		if (N1 > 0) N1 = 1; else N1 = -1;		if (N2 > 0) N2 = 1; else N2 = -1;		if (N1 * N2 < 0) ++Ans;	}	printf("%d\n", Ans);	return 0;}

 

Problem E

题目大意:

  给定一个序列 A[n] ,还有一些实数对 (i, j) ,满足 i + j 为奇数。每次可以进行一次操作:选取一个实数对 (i, j),如果 A[i] 和 A[j] 不互质,就可以 ++Ans,然后将他们同除以一个大于 1 的公因子。这些实数对可重复利用。问 Ans 最多可以多大。

 

题目分析:

  题目中的实数对为 (i, j) 满足 i + j 为奇数,所以 i 与 j 一个是奇数,一个是偶数。那么所有的实数对就相当于在每对 i,j 之间的连边,这样就组成一个二分图,只有下标为偶数的数和下标为奇数的数可能连边,奇数与奇数,偶数与偶数不能连边。

  这个题的操作描述中的网络流气息十分明显...那么就是求最大流,下面我们来建图:

  对于每个下标为奇数的数,将它分解质因数,从每个(质因数点1)向它连容量为这个质因数的指数的边。

  对于每个下标为偶数的数,将它分解质因数,从它向每个(质因数点2)连容量为这个质因数的指数的边。

  对于每个(质因数点1),我们从 S 向它连 INF 边;对于每个(质因数点2),我们从它向 T 连 INF 边。

  对于每个实数对,我们从奇数向偶数连 INF 边。

  这样求最大流就可以了。

 

代码:

 

Codeforces Round #284 (Div. 2)