2016ACM/ICPC亚洲区沈阳站 Solution

A - Thickest Burger

水。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t;
 5 int a, b;
 6 
 7 int main()
 8 {
 9     scanf("%d" ,&t);
10     while (t--)
11     {
12         scanf("%d%d", &a, &b);
13         if (a > b) swap(a, b);
14         printf("%d\n", a + b * 2);
15     }
16     return 0;
17 }
View Code

 

B - Relative atomic mass

水。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t;
 5 char s[100];
 6 
 7 int main()
 8 {
 9     scanf("%d", &t);
10     while (t--)
11     {
12         scanf("%s", s);
13         int res = 0;
14         for (int i = 0, len = strlen(s); i < len; ++i)
15         {
16             if (s[i] == 'H') res += 1;
17             if (s[i] == 'C') res += 12;
18             if (s[i] == 'O') res += 16;
19         }
20         printf("%d\n", res);
21     }
22     return 0;
23 }
View Code

 

C - Recursive sequence

题意:求$F[n] = F[n - 1] + 2 \cdot F[n - 2] + n^4$

思路:考虑

$n^4 = (n - 1)^4 + 4 \cdot (n - 1) ^ 3 + 6 \cdot (n - 1) ^2 + 4 \cdot (n - 1) ^ 2 + (n - 1) + 1$

然后进行递推即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 
 6 const ll MOD = 2147493647;
 7 
 8 int t;
 9 ll n, a, b;
10 
11 struct node
12 {
13     ll a[7][7];
14     node () { memset(a, 0, sizeof a); }
15     node operator * (const node &r) const
16     {
17         node ans = node();
18         for (int i = 0; i < 7; ++i) for (int j = 0; j < 7; ++j) for (int k = 0; k < 7; ++k)
19             ans.a[i][j] = (ans.a[i][j] + a[i][k] * r.a[k][j] % MOD) % MOD;
20         return ans;
21     }
22 };
23 
24 ll tmp[7][7] = 
25 {
26     1, 1, 0, 0, 0, 0, 0,
27     2, 0, 0, 0, 0, 0, 0,
28     1, 0, 1, 0, 0, 0, 0,
29     4, 0, 4, 1, 0, 0, 0,
30     6, 0, 6, 3, 1, 0, 0,
31     4, 0, 4, 3, 2, 1, 0,
32     1, 0, 1, 1, 1, 1, 1,
33 };
34 
35 ll tmp2[7] = 
36 {
37     0, 0, 16, 8, 4, 2, 1,
38 };
39 
40 node qmod(ll n)
41 {
42     node base = node();
43     for (int i = 0; i < 7; ++i) for (int j = 0; j < 7; ++j)
44         base.a[i][j] = tmp[i][j];
45     node res = node();
46     for (int i = 0; i < 7; ++i) res.a[0][i] = tmp2[i];
47     while (n)
48     {
49         if (n & 1) res = res * base;
50         base = base * base;
51         n >>= 1;
52     }
53     return res;
54 }
55 
56 int main()
57 {
58     scanf("%d", &t);
59     while (t--)
60     {
61         scanf("%lld%lld%lld", &n, &a, &b);
62         if (n == 1) printf("%lld\n", a);
63         else if (n == 2) printf("%lld\n", b);
64         else
65         {
66             tmp2[0] = b; tmp2[1] = a;
67             printf("%lld\n", qmod(n - 2).a[0][0]);
68         }
69     }
70     return 0;
71 }
View Code

 

D - Winning an Auction

留坑。

 

E - Counting Cliques

题意:给出n个点,m条边,求点集大小为S的完全图个数

思路:以每个点为起点搜有多少完全图

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e2 + 10;
 6 
 7 int n, m, s;
 8 int ans;
 9 int arr[maxn], tot;
10 int mp[maxn][maxn];
11 vector<int>G[maxn];
12 
13 void Init(int N)
14 {
15     ans = 0;
16     for(int i = 1; i <= N; ++i)
17     {
18         G[i].clear();
19         mp[i][i] = 1;
20         for(int j = i + 1; j <= N; ++j)
21         {
22             mp[i][j] = mp[j][i] = 0;
23         }
24     }
25 }
26 
27 void DFS(int u, int cnt)
28 {
29     if(cnt == s)
30     {
31         ++ans;
32         return ;
33     }
34     for(auto it: G[u])
35     {
36         bool flag = true;
37         for(int i = 0; i < tot; ++i)
38         {
39             if(!mp[arr[i]][it]) 
40             {
41                 flag = false;
42                 break;
43             }
44         }
45         if(flag)
46         {
47             arr[tot++] = it;
48             DFS(it, cnt + 1);
49             tot--;
50         }
51     }
52 }
53 
54 int main()
55 {
56     int t;
57     scanf("%d", &t);
58     while(t--)
59     {
60         scanf("%d %d %d", &n, &m, &s);
61         Init(n);
62         for(int i = 1; i <= m; ++i)
63         {
64             int u, v;
65             scanf("%d %d", &u, &v);
66             G[u].push_back(v);
67             mp[u][v] = mp[v][u] = 1;
68         }
69         for(int i = 1; i <= n; ++i)
70         {
71             tot = 0;
72             arr[tot++] = i;
73             DFS(i, 1);
74         }
75         printf("%d\n", ans);
76     }
77     return 0;
78 }
View Code

 

 

G - Do not pour out

题意:有一个底部为直径为2的圆,高度为2的桶,现在里面有高度为h的液体,将桶倾斜至最大,求上表面面积

思路:分类,若经过没经过底部则为PI / cos(2.0-d)

否则二分+积分求面积

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const double eps = 1e-20;
 6 const double PI = acos(-1.0);
 7 
 8 int sgn(double x)
 9 {
10     if(fabs(x) < eps) return 0;
11     else return x > 0 ? 1 : -1;
12 }
13 
14 double d;
15 
16 double calc(double arc)
17 {
18     return PI * cos(arc) - arc * cos(arc) + sin(arc) - sin(arc) * sin(arc) * sin(arc) / 3.0;
19 }
20 
21 int check(double mid)
22 {
23     double tmp = (calc(acos(2.0 * tan(mid) - 1.0)) - calc(PI)) / tan(mid);
24     return sgn(tmp - d * PI);
25 }
26 
27 double get(double l, double r)
28 {
29     if(check(l) == 0) return l;
30     int cnt = 256;
31     while(cnt--)
32     {
33         double mid = (l + r) / 2.0;
34         int tmp = check(mid);
35         if(tmp == 0) return mid;
36         if(tmp == 1) r = mid;
37         if(tmp == -1) l = mid;
38     }
39     return l;
40 }
41 
42 int main()
43 {
44     int t;
45     scanf("%d", &t);
46     while(t--)
47     {
48         scanf("%lf", &d);
49         if(sgn(d) == 0)
50         {
51             printf("0.00000\n");
52         }
53         else if(sgn(d - 1) > 0)
54         {
55             double arc = atan(2.0 - d);
56             double ans = PI / cos(arc);
57             printf("%.5f\n", ans);
58         }
59         else
60         {
61             double tmp = get(eps, PI / 4.0);
62             double t1 = 2.0 * tan(tmp) - 1.0;
63             double arc = acos(t1);
64             double ans = PI - arc + cos(arc) * sin(arc);
65             ans = ans / sin(tmp);
66             printf("%.5f\n", ans);
67         }
68     }
69     return 0;
70 }
View Code

 

H - Guessing the Dice Roll

留坑。

 

I - The Elder

题意:给出一棵树,每个点到根节点1的方式可以是连续走,也可以经过一个点消耗时间p,使得重新计算所经过路径,求每个点到根节点最小的最大时间   时间为$L^2$

思路:考虑朴素的转移 $F[i] = min(F[j] + p + (sum[i] - sum[j]) ^ 2) (j 为 i 的祖先们)$

拆分式子

$F[i] = F[j] + p + {sum[i]} ^ 2 - 2 \cdot sum[i] \cdot sum[j] + {sum[j]} ^ 2$

$F[j] = F[i] + 2 \cdot sum[i] \cdot sum[j] - p - {sum[i]} ^ 2 - {sum[j]} ^ 2$

考虑斜率优化

树上的单调队列优化可以通过标记最后一个更改的值,然后还原(XHT)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int maxn = 1e5 + 10;
 8 
 9 struct Edge{
10     int to, nxt;
11     ll w;
12     Edge(){}
13     Edge(int to, int nxt, ll w): to(to), nxt(nxt), w(w){}
14 }edge[maxn << 1];
15 
16 ll ans;
17 ll dis[maxn];
18 ll dp[maxn];
19 int n, p;
20 int que[maxn];
21 int head[maxn], tot;
22 
23 void Init(int N)
24 {
25     for(int i = 1; i <= N; ++i) head[i] = -1;
26     tot = ans = 0;
27 }
28 
29 void addedge(int u, int v, ll w)
30 {
31     edge[tot] = Edge(v, head[u], w);
32     head[u] = tot++;
33 }
34 
35 ll dy(int j, int k)
36 {
37     return dp[j] - dp[k] + dis[j] * dis[j] - dis[k] * dis[k];
38 }
39 
40 ll dx(int j, int k)
41 {
42     return 2 * (dis[j] - dis[k]);
43 }
44 
45 void DFS(int u, int fa, int l, int r)
46 {
47     int remind = -1;
48     
49     if(u != 1)
50     {
51         while(l < r && dy(que[l + 1], que[l]) <= dis[u] * dx(que[l + 1], que[l])) l++;
52 //        cout << u << " " << que[l] << " " << dp[que[l]] + p + (dis[u] - dis[que[l]]) * (dis[u] - dis[que[l]]) << endl;
53         dp[u] = min(dis[u] * dis[u], dp[que[l]] + p + (dis[u] - dis[que[l]]) * (dis[u] - dis[que[l]]));
54         while(l < r && dy(que[r], que[r - 1]) * dx(u, que[r]) >= dy(u, que[r]) * dx(que[r], que[r - 1])) r--;
55         remind = que[++r];
56         que[r] = u;
57     }
58 
59     ans = max(ans, dp[u]);
60 
61     for(int i = head[u]; ~i; i = edge[i].nxt)
62     {
63         int v = edge[i].to;
64         if(v == fa) continue;
65         dis[v] = dis[u] + edge[i].w;
66         DFS(v, u, l, r);
67     }
68 
69     if(remind != -1) que[r] = remind;
70 }
71 
72 
73 int main()
74 {
75     int t;
76     scanf("%d", &t);
77     while(t--)
78     {
79         scanf("%d %d", &n, &p);
80         Init(n);
81         for(int i = 1; i < n; ++i)
82         {
83             int u, v, w;
84             scanf("%d %d %d", &u, &v ,&w);
85             addedge(u, v, w);
86             addedge(v, u, w);
87         }
88         DFS(1, -1, 1, 0);
89 //        for(int i = 1; i <= n; ++i) cout << i << " " << dp[i] << endl;
90         printf("%lld\n", ans);
91     }
92     return 0;
93 }
View Code

 

J - Query on a graph

留坑。

 

K - New Signal Decomposition

留坑。

 

L - A Random Turn Connection Game

留坑。

 

M - Subsequence

留坑。

posted @ 2018-10-14 17:03  Dup4  阅读(249)  评论(0编辑  收藏  举报