[Contest]2017 ACM/ICPC Asia Regional Qingdao Online(施工中...)
1001 Apple
题意
给定一个三角形,判断一个点是否在其外接圆外。
题解
考虑求出外接圆圆心,简单比较即可。
根据计算几何知识,我们知道三角形三个顶点分别为$(x_1,y_1)(x_2,y_2)(x_3,y_3)$,则外心为$(\frac{\begin{vmatrix}
x_12+y_12 & y_1 & 1 \newline
x_22+y_22 & y_2 & 1 \newline
x_32+y_32 & y_3 & 1
\end{vmatrix}}{2\times\begin{vmatrix}
x_1 & y_1 & 1 \newline
x_2 & y_2 & 1 \newline
x_3 & y_3 & 1
\end{vmatrix}},\frac{\begin{vmatrix}
x_1 & x_12+y_12 & 1 \newline
x_2 & x_22+y_22 & 1 \newline
x_3 & x_32+y_32 & 1
\end{vmatrix}}{2\times\begin{vmatrix}
x_1 & y_1 & 1 \newline
x_2 & y_2 & 1 \newline
x_3 & y_3 & 1
\end{vmatrix}})$。
$PS:C++$爆了精度,我是用$Java$的$BigDecimal$类过的。
代码
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static BigDecimal Sqr(BigDecimal x) {
return x.multiply(x);
}
public static BigDecimal Distance(BigDecimal x1, BigDecimal y1, BigDecimal x2, BigDecimal y2) {
return Sqr(x1.subtract(x2)).add(Sqr(y1.subtract(y2)));
}
public static BigDecimal Determinant(BigDecimal a, BigDecimal b, BigDecimal c, BigDecimal d, BigDecimal e, BigDecimal f, BigDecimal g, BigDecimal h, BigDecimal i) {
BigDecimal p1 = a.multiply(e).multiply(i);
BigDecimal p2 = b.multiply(f).multiply(g);
BigDecimal p3 = c.multiply(d).multiply(h);
BigDecimal n1 = c.multiply(e).multiply(g);
BigDecimal n2 = b.multiply(d).multiply(i);
BigDecimal n3 = a.multiply(f).multiply(h);
return p1.add(p2).add(p3).subtract(n1).subtract(n2).subtract(n3);
}
public static String Circumcenter(BigDecimal x1, BigDecimal y1, BigDecimal x2, BigDecimal y2, BigDecimal x3, BigDecimal y3, BigDecimal xp, BigDecimal yp) {
BigDecimal one = new BigDecimal("1");
BigDecimal two = new BigDecimal("2");
BigDecimal xc = Determinant(Sqr(x1).add(Sqr(y1)), y1, one, Sqr(x2).add(Sqr(y2)), y2, one, Sqr(x3).add(Sqr(y3)), y3, one);
xc = xc.divide(Determinant(x1, y1, one, x2, y2, one, x3, y3, one).multiply(two));
BigDecimal yc = Determinant(x1, Sqr(x1).add(Sqr(y1)), one, x2, Sqr(x2).add(Sqr(y2)), one, x3, Sqr(x3).add(Sqr(y3)), one);
yc = yc.divide(Determinant(x1, y1, one, x2, y2, one, x3, y3, one).multiply(two));
BigDecimal r = Sqr(x1.subtract(xc)).add(Sqr(y1.subtract(yc)));
BigDecimal d = Sqr(xp.subtract(xc)).add(Sqr(yp.subtract(yc)));
return d.compareTo(r) == 1 ? "Accepted" : "Rejected";
}
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int T = Integer.parseInt(reader.nextLine());
while ((T--) > 0) {
String string = reader.nextLine();
String pos[] = string.split(" ");
BigDecimal x1 = new BigDecimal(pos[0]); BigDecimal y1 = new BigDecimal(pos[1]);
BigDecimal x2 = new BigDecimal(pos[2]); BigDecimal y2 = new BigDecimal(pos[3]);
BigDecimal x3 = new BigDecimal(pos[4]); BigDecimal y3 = new BigDecimal(pos[5]);
BigDecimal x = new BigDecimal(pos[6]); BigDecimal y = new BigDecimal(pos[7]);
System.out.println(Circumcenter(x1, y1, x2, y2, x3, y3, x, y));
}
reader.close();
}
}
1002 Bomberman
题意
题解
代码
1003 The Dominator of Strings
题意
求若干串中一个“支配串”使得其他串都是它的子串。
题解
首先“支配串”的一定是长度最大的那一个。然后我们考虑对于每个串在“支配串”中$string::find$即可。
数据太水让我给水过去了,题目没有给出串总数的范围,复杂度玄学......
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<string> s;
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
while (T--) {
int n; cin >> n;
int len = 0; string dom = ""; s.clear();
for (int i = 1; i <= n; i++) {
string str; cin >> str; s.push_back(str);
if (str.size() > len) len = str.size(), dom = str;
}
bool flag = 1;
for (auto str : s) {
if (dom.find(str) != str.npos) continue;
else {
flag = 0; break;
}
}
cout << (flag ? dom : "No") << "\n";
}
return 0;
}
1004 The Intersection
题意
题解
代码
1005 King's Visit
题意
题解
代码
1006 Pythagoras
题意
题解
代码
1007 Zuma
题意
题解
代码
1008 Chinese Zodiac
题意
给定两个人的生肖,第一个人比第二个人大,求年龄差最小是多少。
题解
暴力。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int s = 1, x = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return s * x;
}
map<string, int> sgn;
int main() {
sgn["rat"] = 0;
sgn["ox"] = 1;
sgn["tiger"] = 2;
sgn["rabbit"] = 3;
sgn["dragon"] = 4;
sgn["snake"] = 5;
sgn["horse"] = 6;
sgn["sheep"] = 7;
sgn["monkey"] = 8;
sgn["rooster"] = 9;
sgn["dog"] = 10;
sgn["pig"] = 11;
int T; cin >> T;
while (T--) {
string a1, a2;
cin >> a1 >> a2;
cout << (a1 == a2 ? 12 : (sgn[a2] - sgn[a1] + 12) % 12) << endl;
}
return 0;
}
1009 Smallest Minimum Cut
题意
求有向图最小割的最少边数。
题解
这不是HDOJ原题么?......
我们考虑两种方法:
- 第一种是跑两遍最大流,第一遍最大流之后把满流量的边容量$+1$,不是满流量的边容量改为$INF$,再跑第二遍最大流即为答案。因为容易证明:第一遍最大流之后满流量的边是最小割上的边。
- 第二种是建边时扩大边权$w'=m\times w+1$,这样求出来的最大流为$\frac{flow}{m}$,最小割最少边数为$flow\mod m$。因为容易证明:原图中最小割的边满流量$w$,新图中也一定能满流量$m\times w$,而多余的$1$容量,相当于第一种方法里面跑的第二遍最大流。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int s = 1, x = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return s * x;
}
const int N = 209;
const int M = 4009;
const int INF = 0x3f3f3f3f;
int n, m, s, t, tot;
int head[N];
struct Edge {
int v, nxt, cap, flw;
} e[M];
void addEdge(int u, int v, int cap) {
e[tot].v = v; e[tot].nxt = head[u]; e[tot].cap = cap; e[tot].flw = 0; head[u] = tot++;
e[tot].v = u; e[tot].nxt = head[v]; e[tot].cap = 0; e[tot].flw = 0; head[v] = tot++;
}
int lvl[N], gap[N];
void bfs() {
memset(lvl, -1, sizeof(lvl));
memset(gap, 0, sizeof(gap));
lvl[t] = 0; gap[ lvl[t] ]++;
queue<int> q; q.push(t);
while(!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].v;
if (lvl[v] != -1) continue;
lvl[v] = lvl[u] + 1; gap[ lvl[v] ]++;
q.push(v);
}
}
}
int pre[N], cur[N];
int ISAP() {
bfs();
memset(pre, -1, sizeof(pre));
memcpy(cur, head, sizeof(head));
int u = pre[s] = s;
int flw = 0, aug = INF;
gap[0] = n;
while (lvl[s] < n) {
bool flag = false;
for (int &i = cur[u]; i != -1; i = e[i].nxt) {
int v = e[i].v;
if (e[i].cap != e[i].flw && lvl[u] == lvl[v] + 1) {
flag = true; pre[v] = u; u = v;
aug = min(aug, e[i].cap - e[i].flw);
if (v == t) {
flw += aug;
for (u = pre[v]; v != s; v = u, u = pre[u]) {
e[ cur[u] ].flw += aug;
e[ cur[u] ^ 1 ].flw -= aug;
}
aug = INF;
}
break;
}
}
if (flag) continue;
int minLevel = n;
for (int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].v;
if (e[i].cap != e[i].flw && lvl[v] < minLevel) {
minLevel = lvl[v];
cur[u] = i;
}
}
if (--gap[ lvl[u] ] == 0) break;
lvl[u] = minLevel + 1; gap[ lvl[u] ]++; u = pre[u];
}
return flw;
}
int main() {
int T = read();
while (T--) {
n = read(), m = read(), s = read(), t = read(), tot = 0;
memset(head, -1, sizeof(head));
for (int i = 1; i <= m; i++) {
int u = read(), v = read(), w = read();
addEdge(u, v, w * m + 1);
}
printf("%d\n", ISAP() % m);
}
return 0;
}
1010 Brute Force Sorting
题意
题解
代码
1011 A Cubic number and A Cubic Number
题意
判断一个素数$p$能否表示成立方差。
题解
我们考虑$p=a3-b3=(a-b)(a2+ab+b2)$,要满足$p$是素数,必须有$a-b=1$。因此$p=(b+1)2+(b+1)b+b2=3b^2+3b+1$,$p-1=3b(b+1)$。直接枚举$b$即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
ll s = 1, x = 0; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return s * x;
}
inline bool check(ll p) {
p -= 1;
if (p % 3 != 0) return 0;
p /= 3;
for (ll a = 1; a * (a + 1) <= p; a++) {
if (a * (a + 1) == p) return 1;
}
return 0;
}
int main() {
ll T = read();
while (T--) {
ll p = read();
puts(check(p) ? "YES" : "NO");
}
return 0;
}