2017 ACM/ICPC Asia Regional Qingdao Online解题报告(部分)

HDU 6206 Apple

题意:

给出四个点的坐标(每个点的坐标值小于等于1,000,000,000,000),问最后一个点是否在前三个点组成的三角形的外接圆内,是输出Accept,否输出Rejected

解题思路:

题意很好理解,就是判断一个点是否在一个圆内,或者说一个点到圆心的距离是否大于半径,关键是大整数和精度问题,题解中给出了java的解法。

设x0,y0为圆心,有圆心到三个顶点的距离相等,列出如下两个式子:

(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0) = (x2-x0)*(x2-x0)+(y2-y0)*(y2-y0).

(x2-x0)*(x2-x0)+(y2-y0)*(y2-y0) = (x3-x0)*(x3-x0)+(y3-y0)*(y3-y0).

化简可得:

2(x2-x1)x0 + 2(y2-y1)y0 = x2^2 + y2^2 - x1^2 - y1^2.

2(x3-x2)x0 + 2(y3-y2)y0 = x3^2 + y3^2 - x2^2 - y2^2.

令a1 = 2*(x2-x1);

 b1 = 2*(y2-y1);

 c1 = x2^2 + y2^2 - x1^2 - y1^2;

 a2 = 2*(x3-x2);

 b2 = 2*(y3-y2);

 c2 = x3^2 + y3^2 - x2^2 - y2^2;

a1*x0 + b1*y0 = c1;

a2*x0 + b2*y0 = c2;

根据克莱姆法则(具体参见记法2)可得

x0 = (c1*b2 - b1*c2)/(a1*b2 - b1*a2);

y0 = (a1*c2 - c1*a2)/(a1*b2 - b1*a2);

由两点间距离公式得

r = (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);

d = (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);(x-x0)*(x-x0)+(y-y0)*(y-y0);(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)

由于涉及到大整数和高精度,使用Java中的BidDecimal代码如下:

 1 import java.math.BigDecimal;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5 
 6     public static void main(String[] args) {
 7         Scanner in = new Scanner(System.in);
 8         int T = in.nextInt();
 9         while(T-- > 0) {
10             BigDecimal x1 = in.nextBigDecimal();
11             BigDecimal y1 = in.nextBigDecimal();
12             BigDecimal x2 = in.nextBigDecimal();
13             BigDecimal y2 = in.nextBigDecimal();
14             BigDecimal x3 = in.nextBigDecimal();
15             BigDecimal y3 = in.nextBigDecimal();
16             BigDecimal x = in.nextBigDecimal();
17             BigDecimal y = in.nextBigDecimal();
18             
19             BigDecimal a1 = x2.subtract(x1).multiply(BigDecimal.valueOf(2));
20             BigDecimal b1 = y2.subtract(y1).multiply(BigDecimal.valueOf(2));
21             BigDecimal c1 = x2.pow(2).add(y2.pow(2)).subtract(x1.pow(2)).subtract(y1.pow(2));
22             
23             BigDecimal a2 = x3.subtract(x2).multiply(BigDecimal.valueOf(2));
24             BigDecimal b2 = y3.subtract(y2).multiply(BigDecimal.valueOf(2));
25             BigDecimal c2 = x3.pow(2).add(y3.pow(2)).subtract(x2.pow(2)).subtract(y2.pow(2));
26             
27             BigDecimal x0 = b2.multiply(c1).subtract(b1.multiply(c2)).divide(a1.multiply(b2).subtract(b1.multiply(a2)));
28             BigDecimal y0 = a1.multiply(c2).subtract(c1.multiply(a2)).divide(a1.multiply(b2).subtract(b1.multiply(a2)));
29             
30             BigDecimal r = x1.subtract(x0).pow(2).add(y1.subtract(y0).pow(2));
31             BigDecimal d = x.subtract(x0).pow(2).add(y.subtract(y0).pow(2));
32             if(1 == d.compareTo(r))
33                 System.out.println("Accepted");
34             else
35                 System.out.println("Rejected");
36         }
37     }
38     
39 }

HDU 6208 The Dominator of Strings

题意:

给出n个串,问是否存在一个串能够包含这n个串。

解题思路:

AC自动机的模板题,注意输入字符串的数组开大一点就行了。

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 const int K = 26;
 5 const int maxn = 100000 + 10;
 6 struct Node {
 7     Node *ch[K], *fail;
 8     int mc;
 9     void clear(){
10         memset(this, 0, sizeof(Node));
11     }
12 };
13 
14 Node *que[maxn*2];
15 struct AC {
16     Node nodes[maxn], *root, *sroot, *cur;
17     Node* newNode() {
18         cur->clear();
19         return cur++;
20     }
21     void clear() {
22         cur = nodes;
23         sroot = newNode();
24         root = newNode();
25         root->fail = sroot;
26         for(int i = 0; i < K; i++) {
27             sroot->ch[i] = root;
28         }
29         sroot->mc = -1;
30     }
31     void insert(char *s) {
32         Node* t = root;
33         for(; *s; s++) {
34             int x = *s - 'a';
35             if(t->ch[x] == NULL)
36                 t->ch[x] = newNode();
37             t=t->ch[x];
38         }
39         t->mc++;
40     }
41     void build() {
42         int p = 0, q = 0;
43         que[q++] = root;
44         while(p != q) {
45             Node *t = que[p++];
46             for(int i = 0; i < K; i++) {
47                 if(t->ch[i]) {
48                     t->ch[i]->fail = t->fail->ch[i];
49                     que[q++] = t->ch[i];
50                 } 
51                 else 
52                     t->ch[i] = t->fail->ch[i];        
53             }
54         }
55     }
56     int run(char *s) {
57         int ans = 0;
58         Node* t = root;
59         for(; *s; s++) {
60             int x = *s - 'a';
61             t = t->ch[x];
62             for(Node* u = t; u->mc != -1; u = u->fail) {
63                 ans += u->mc;
64                 u->mc = -1;
65             }
66         }
67         return ans;
68     }
69 }ac;
70 int n;
71 char s[100100], t[100110];
72 int main()
73 {
74     int T;
75     scanf("%d", &T);
76     while(T--) {
77         scanf("%d", &n);
78         ac.clear();
79         int maxl = 0;
80         memset(t, 0, sizeof(t));
81         for(int i = 0; i < n; i++) {
82             scanf(" %s", s);
83             int len = strlen(s);
84             if(len > maxl) {
85                 maxl = len;
86                 strcpy(t, s);
87             }
88             ac.insert(s);
89         }        
90         ac.build();
91         
92         if(ac.run(t) == n)
93             puts(t);
94         else
95             puts("No");
96     }
97     return 0;
98 }

HDU 6216 A Cubic number and A Cubic Number

题意:

判断一个质数p,是否是两个立方数之差

解题思路:

由题(x^3 - y^3) = p

  即(x - y) * (x^2 - 2*x*y + y^2) = p

由于p是质数,所以(x - y) = 1,即x = y + 1,代入原式得

3 * y * y + 3 * y + 1 = p

枚举10^6以内的y,对于每一个p搜索是否存在即可。

 1 #include <cstdio>
 2 typedef long long ll;
 3 const ll maxn = 1e6 + 10;
 4 ll ls[maxn];
 5 
 6 int main()
 7 {
 8     int T;
 9     ll p;
10     for(ll i = 0; i < maxn; i++) {
11         ls[i] = 3 * i * i + 3 * i + 1;        
12     }
13     scanf("%d", &T);
14     while(T--) {
15         scanf("%lld", &p);
16         bool f = 0;
17         int le = -1, ri = maxn;
18         while(ri - le > 1) {
19             int mid = (ri + le) >> 1;
20             if(p == ls[mid]) {
21                 f = 1;
22                 break;
23             } else if(p > ls[mid])
24                 le = mid;
25             else
26                 ri = mid;
27         }
28         if(f)
29             puts("YES");
30         else
31             puts("NO");
32     }
33     return 0;
34 }

 HDU 6213 Chinese Zodiac

题意:

前提是女的比男的大,给出生肖,问两人的最小年龄差是多少

 1 #include <cstdio>
 2 #include <map>
 3 #include <cstring>
 4 #include <string>
 5 #include <iostream>
 6 using namespace std;
 7 
 8 const string ls[12] = {"rat", "ox", "tiger", "rabbit", "dragon", "snake", "horse", "sheep", 
 9 "monkey", "rooster", "dog", "pig"};
10 
11 int main()
12 {
13     int T;
14     map<string, int> mp;
15     for(int i = 0; i < 12; i++) {
16         mp[ls[i]] = i + 1;
17     }
18     string a, b;    
19     cin >> T;
20     while(T--) {
21         cin >> a >> b;
22         int c = mp[a];
23         int d = mp[b];
24         int ans = d - c;
25         
26         if(ans <= 0)
27             ans += 12;
28         cout << ans <<endl;
29     }
30     return 0;
31 }
原文地址:https://www.cnblogs.com/wenzhixin/p/9768200.html