Codeforces Round #513-ABCD
ABC現場做出,漲了八十幾分吧。D有點思路不知道怎麽實現,賽後看題解發現巨簡單,想得太復雜了。藍瘦。
A----http://codeforces.com/contest/1060/problem/A
題意:給定n位數,問能組成多少電話號碼。電話號碼是一個以8位開頭的11位數
思路:統計一下8的個數,計算一下n/11的個數,兩者取較小值即為答案
1 #include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6View Code#include<cstring> 7 #include<map> 8 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 typedef long long int LL; 12 13 int n; 14 const int maxn = 105; 15 int dig[10]; 16 17 int main() 18 { 19 while(scanf("%d", &n) != EOF){ 20 char str[maxn]; 21 scanf("%s", str);22 memset(dig, 0, sizeof(dig)); 23 int cnt = 0; 24 for(int i = 0; i < n; i++){ 25 dig[str[i] - ‘0‘]++; 26 cnt++; 27 } 28 29 int ans = min(dig[8], cnt / 11); 30 cout<<ans<<endl; 31 } 32 return 0; 33 }
B---http://codeforces.com/contest/1060/problem/B
題意:給定一個n,要求兩個數 a+b=n並且a的各數位之和和b的各數位之和相加是最大的,輸出這個和
思路:有一個數一定是比n少一位的,全由9構成的數。
1 #include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<map> 8 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 typedef long long int LL; 12 13 LL n; 14 15 int main() 16 { 17 while(scanf("%I64d", &n) != EOF){ 18 int dig = 0; 19 LL tmp = n; 20 while(tmp){ 21 tmp /= 10; 22 dig++; 23 } 24 25 dig--; 26 int ans = dig * 9; 27 tmp = n; 28 LL ten = 1; 29 while(dig){ 30 tmp -= ten * 9; 31 ten *= 10; 32 dig--; 33 } 34 while(tmp){ 35 ans += tmp % 10; 36 tmp /=10; 37 } 38 printf("%d\n", ans); 39 } 40 return 0; 41 }View Code
C---http://codeforces.com/contest/1060/problem/C
題意:給定兩個數組a和b,矩陣c(i,j) = ai * bj,求矩陣c的一個子矩陣使得子矩陣中所有元素和小於x,並且要讓這個子矩陣的元素個數盡可能多
思路:c是不需要算出來的。找c的一個子矩陣相當於分別找a和b中連續的一段區間。
首先預處理出a和b中,連續的長度為i的區間之和最小的。asum[i]即為a數組中,連續的長度為i的總和最小的區間
因為要讓元素個數盡可能多,那麽就應該要找和最小值
然後分別枚舉子矩陣的行數和列數,找到和小於x且元素個數最多的
1 #include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<map> 8 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 typedef long long int LL; 12 13 int n, m; 14 const int maxn = 2005; 15 LL a[maxn], b[maxn], x; 16 LL suma[maxn], sumb[maxn]; 17 LL asum[maxn], bsum[maxn]; 18 19 int main() 20 { 21 while(scanf("%d%d", &n, &m) != EOF){ 22 memset(suma, 0, sizeof(suma)); 23 memset(sumb, 0, sizeof(sumb)); 24 for(int i = 1; i <= n; i++){ 25 scanf("%I64d", &a[i]); 26 suma[i] = suma[i - 1] + a[i]; 27 } 28 for(int i = 1; i <= m; i++){ 29 scanf("%I64d", &b[i]); 30 sumb[i] = sumb[i - 1] + b[i]; 31 } 32 scanf("%I64d", &x); 33 34 memset(asum, inf, sizeof(asum)); 35 memset(bsum, inf, sizeof(bsum)); 36 for(int i = 1; i <= n; i++){ 37 for(int pos = i; pos <= n; pos++){ 38 asum[i] = min(suma[pos] - suma[pos - i], asum[i]); 39 } 40 } 41 for(int i = 1; i <= m; i++){ 42 for(int pos = i; pos <= m; pos++){ 43 bsum[i] = min(sumb[pos] - sumb[pos - i], bsum[i]); 44 } 45 } 46 47 LL ans = 0; 48 for(int i = n; i >= 1; i--){ 49 for(int j = m; j >= 1; j--){ 50 if(bsum[j] * asum[i] <= x){ 51 if(i * j > ans){ 52 ans = i * j; 53 } 54 } 55 } 56 } 57 58 printf("%I64d\n", ans); 59 } 60 return 0; 61 }View Code
D---http://codeforces.com/contest/1060/problem/D
題意:有n個人坐成一圈 每個人都要求他的左邊至少有a[i]個空位,右邊有b[i]個空位。問要滿足所有人的要求至少需要多少凳子。
思路:
現場的思路是所有人和空位之和。每次都找到左邊空位最大的那個人,和右邊空位最大的那個進行合並,總數就減去。合並之後相當於形成一個新的人。但是一時想不出來我形成新的人之後要怎麽繼續維護,難道每次都排序,肯定是不夠的。
其實,合並並沒有影響左邊的數組和右邊的數組。合並之後的左邊和右邊原來就在數組之中。
所以只需要先對a和b數組分別排序,每次取出a和b中的最大值。答案加上這兩個最大之中的較大。最後答案加上n就行了。
1 #include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<map> 8 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 typedef long long LL; 12 13 int n; 14 const int maxn = 1e5 + 5; 15 int a[maxn], b[maxn]; 16 17 int main() 18 { 19 while(scanf("%d", &n) != EOF){ 20 for(int i = 0; i < n; i++){ 21 scanf("%d%d", &a[i], &b[i]); 22 } 23 sort(a, a + n); 24 sort(b, b + n); 25 26 LL ans = n; 27 for(int i = 0; i < n; i++){ 28 ans += max(a[i], b[i]); 29 } 30 printf("%I64d\n", ans); 31 } 32 return 0; 33 }View Code
Codeforces Round #513-ABCD