Codeforces Round #691 (Div. 2)

B. Move and Turn(数学)

题意:

从原点出发走n步,只能上下左右四个方向,且除了第一步之外每次走都要做九十度的转弯。求最终可以到达的位置的个数

题解:

 1 /*
 2 当n为偶数时,可以看作水平走了 k = n/2 步,垂直方向也走了 k = n/2 步,水平方向上有 -k, -k + 2, -k + 4, ..., k - 2, k.
 3 共 k + 1 个位置可以到达,垂直方向同理,因此可以到达 (k + 1) * (k + 1) 个位置
 4 当n为奇数时,可以看作水平多走一步或者垂直方向上多走了一步。因此有 2 * (k + 1) * (k + 2) 个位置可以到达,此时水平多走一步到达的
 5 位置是唯一的(记作集和1),垂直方向多走一步到达的位置也是唯一的(记作集和2),且这两个集和无交集,因为水平或垂直方向上两者总是会
 6 至少相差1
 7 */
 8 #include <bits/stdc++.h>
 9 
10 using namespace std;
11 
12 int main()
13 {
14     int n, ans;
15     scanf("%d", &n);
16     int k = n / 2;
17     if (n & 1 ) {
18         ans = 2 * (k + 1) * ( k + 2);
19     }
20     else {
21         ans = (k + 1) * (k + 1);
22     }
23     printf("%d
", ans);
24 }
View Code

C. Row GCD(数论)

题意:

输入n和m (1 <= n, m <= 2*10^5) 

随后输入n个数a[i],

然后输入m个数b[j],

对于每一个b[j],求gcd(a[1] - b[j], a[2] - b[j], ......a[n - b[j])。

题解:

 1 /*
 2 因为 gcd(a, b) = gcd(a - b, b), 对于多个数来说也成立,即gcd(a, b, c, ...) = gcd(a - b, b, c, ...)
 3 因此 gcd(a[0] + b[j], a[1] + b[j], ......, a[n - 1] + b[j]) = gcd(a[0] + b[j], a[1] - a[0], ......, a[n - 1] - a[0])
 4 令GCD = gcd(a[1] - a[0], ......, a[n - 1] - a[0]), 所以结果就是 gcd(GCD, a[0] + b[j])
 5 */
 6 #include <bits/stdc++.h>
 7 
 8 using namespace std;
 9 
10 int n, m;
11 long long a[200005];
12 int main()
13 {
14     cin >> n >> m;
15     for (int i = 0; i < n; ++i) scanf("%lld", &a[i]);
16     sort(a, a + n);
17     long long GCD = 0, b_i, a_0 = a[0];
18     for (int i = 1; i < n; ++i) {
19         GCD = __gcd(GCD, a[i] - a_0);
20     }
21     for (int i = 0; i < m; ++i) {
22         scanf("%lld", &b_i);
23         b_i = __gcd(a_0 + b_i, GCD);
24         printf("%lld
", b_i);
25     }
26     return 0;
27 }
View Code

D. Glass Half Spilled(DP)

题意:

有 n 个杯子,第 i 个杯子的容量为 a[i] 毫升,其中有 b[i] 毫升的水,杯子中的水可以互相倒如另一个杯子中,由于手抖,倒水的时候会洒出来一半,只能留下一半的水,

问 依次取k(1~n)个杯子,可以得到的最多的水量是多少。

题解:

 1 /*
 2 首先,假设取了k个杯子的总容量为 AS,其中包含的水量为 BS,n个杯子总的水量为 B,那么取了这k个杯子获得的水量就是:
 3 min(AS, BS + (B - BS) / 2)。
 4 dp[i][k][j] 表示我们选择到第 i 个杯子时,一共取了 k 个杯子,此时取到杯子的总容量为 j 时所获得的水量是多少,
 5 那么 dp[i][k][j] = max(dp[i - 1][k][j], dp[i - 1][k - 1][j - a[i]] + b[i]),即不取第 i 个杯子或者取第 i 个
 6 杯子。
 7 最后 ans = min(AS, max(dp[n][k][0~A]))
 8 注意开始时只有dp[0][0][0]才是有意义的,其他的无意义的辅助数组都置为 -1 表示不可能事件。
 9 */
10 #include <bits/stdc++.h>
11 
12 using namespace std;
13 
14 const double MIN_NUM = -1e9 - 7;
15 int n, a[101], b[101], A, B, dp[101][101][10001], ans[101];
16 
17 int main()
18 {
19     ios::sync_with_stdio(false);
20     cin.tie(0);
21     cin >> n;
22     for (int i = 1; i <= n; ++i) {
23         cin >> a[i] >> b[i];
24         A += a[i];
25         B += b[i];
26     }
27     memset(dp, -1, sizeof(dp));
28     dp[0][0][0] = 0;
29     for (int i = 1; i <= n; ++i) {
30         for (int k = 0; k <= i; ++k) {
31             for (int j = 0; j <= A; ++j) {
32                 if ((k > 0) && (j >= a[i]) && (dp[i - 1][k - 1][j - a[i]] != -1))
33                     dp[i][k][j] = max(dp[i - 1][k][j], dp[i - 1][k - 1][j - a[i]] + b[i]);
34                 else dp[i][k][j] = dp[i - 1][k][j];
35             }
36         }
37     }
38     for (int k = 1; k <= n; ++k) {
39         double ans = 0;
40         for (int j = 1; j <= A; ++j) {
41             if (dp[n][k][j] == -1) continue;
42             ans = max(min((double)j, (double)dp[n][k][j] / 2.0 + (double)B / 2.0), ans);
43         }
44         cout << fixed << setprecision(9) << ans << endl;
45     }
46     return 0;
47 }
View Code
原文地址:https://www.cnblogs.com/--ZHIYUAN/p/14211896.html