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\n", ans); 24 }
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\n", b_i); 25 } 26 return 0; 27 }
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 }