Codeforces Round #553 (Div. 2)
A、Maxim and Biology
思路:简单贪心。分情况讨论即可。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <iomanip> 8 #include <complex> 9 #include <string> 10 #include <vector> 11 #include <set> 12 #include <map> 13 #include <list> 14 #include <deque> 15 #include <queue> 16 #include <stack> 17 #include <bitset> 18 using namespace std; 19 typedef long long LL; 20 typedef unsigned long long ULL; 21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左 22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向 23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 24 const double eps = 1e-6; 25 const double PI = acos(-1.0); 26 const int maxn = 1e5+5; 27 const int inf = 0x3f3f3f3f; 28 29 int n, ans, s1, s2, s3, s4, sum; 30 char str[55]; 31 32 // A C T G 33 // 0 2 19 6 34 35 int main() { 36 while(cin >> n >> str) { 37 ans = inf; 38 for(int i = 0; i < n - 3; ++i) { 39 s1 = str[i] - 'A'; // A 40 sum = min(s1, 26 - s1); 41 42 s2 = str[i + 1] - 'A'; // C 43 sum += s2 > 2 ? min(abs(s2 - 2), abs(26 - s2 + 2)) : 2 - s2; 44 45 s3 = str[i + 2] - 'A'; // T 46 sum += s3 > 19 ? s3 - 19 : min(abs(s3 - 19), abs(s3 + 26 - 19)); 47 48 s4 = str[i + 3] - 'A'; // G 49 sum += s4 > 6 ? min(s4 - 6, 26 - s4 + 6) : 6 - s4; 50 51 ans = min(ans, sum); 52 } 53 cout << ans << endl; 54 } 55 return 0; 56 }
B、Dima and a Bad XOR
思路:思维。题意就是先从每一行中找一个数,然后将它们全部异或起来,只要满足其异或和大于0,则为"TAK",否则为"NIE"。像这种求可行解的解法一般都很灵活,这里的做法是先将第1列中所有数异或起来,若结果大于0,则直接输出n个1;否则(异或和为0)只需从任意一行中找到一个与该行第一个元素不同的值即可(异或的性质)。若最终找不到一个相异值,则输出"NIE"!
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <iomanip> 8 #include <complex> 9 #include <string> 10 #include <vector> 11 #include <set> 12 #include <map> 13 #include <list> 14 #include <deque> 15 #include <queue> 16 #include <stack> 17 #include <bitset> 18 using namespace std; 19 typedef long long LL; 20 typedef unsigned long long ULL; 21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左 22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向 23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 24 const double eps = 1e-6; 25 const double PI = acos(-1.0); 26 const int maxn = 505; 27 const int inf = 0x3f3f3f3f; 28 29 30 int n, m, now, a[maxn][maxn], ans[maxn]; 31 bool flag; 32 33 int main() { 34 while(cin >> n >> m) { 35 now = 0; 36 memset(ans, 0, sizeof(ans)); 37 for(int i = 0; i < n; ++i) 38 for(int j = 0; j < m; ++j) 39 cin >> a[i][j]; 40 for(int i = 0; i < n; ++i) now ^= a[i][0]; 41 if(now) { 42 cout << "TAK\n"; 43 for(int i = 0; i < n; ++i) cout << 1 << " \n"[i == n - 1]; 44 } 45 else { 46 flag = true; 47 for(int i = 0; i < n; ++i) ans[i] = 1; 48 for(int i = 0; i < n && flag; ++i) { 49 for(int j = 0; j < m && flag; ++j) { 50 if(a[i][j] ^ a[i][0]) { 51 flag = false; 52 ans[i] = j + 1; 53 } 54 } 55 } 56 if(!flag) { 57 cout << "TAK\n"; 58 for(int i = 0; i < n; ++i) cout << ans[i] << " \n"[i == n - 1]; 59 } 60 else cout << "NIE\n"; 61 } 62 } 63 return 0; 64 }
C、Problem for Nazar
思路:数学+规律。题意很简单,就是求区间和。说说我的思路:找规律:
$ 2^0 = 1 $ ---- 1
$ 2^1 = 2 $ ---- 2 4
$ 2^2 = 4 $ ---- 3 5 7 9
$ 2^3 = 8 $ ---- 6 8 10 12 14 16 18 20
$ \cdots $
$ 2^2 - 1 $ $2^4 - 1$ $ 2^6 - 1$ $ \cdots $
奇数项个数 1 5 21 $ \cdots $
偶数项个数 2 10 42 $ \cdots $
对照上面的规律分情况讨论,然后容斥求区间和即可。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <iomanip> 8 #include <complex> 9 #include <string> 10 #include <vector> 11 #include <set> 12 #include <map> 13 #include <list> 14 #include <deque> 15 #include <queue> 16 #include <stack> 17 #include <bitset> 18 using namespace std; 19 typedef long long LL; 20 typedef unsigned long long ULL; 21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左 22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向 23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 24 const double eps = 1e-6; 25 const double PI = acos(-1.0); 26 const int maxn = 1e5+5; 27 const int inf = 0x3f3f3f3f; 28 const LL mod = 1e9+7; 29 30 31 LL lt, rt, now1, now2, cnt1, cnt2, sum1, sum2, cnt3, two[64]; 32 33 int main() { 34 for(int i = 0; i < 63; ++i) two[i] = (1LL << i) - 1LL; // (2^i) - 1 35 while(cin >> lt >> rt) { 36 now1 = now2 = 0LL; 37 while(two[now1 + 1] < lt) ++now1; 38 while(two[now2 + 1] < rt) ++now2; 39 if(now1 & 1) { // 2^{odd} 40 cnt1 = two[now1 + 1] / 3 % mod; 41 cnt2 = 2LL * cnt1 % mod; 42 sum1 = (1LL + (1LL + (cnt1 - 1LL) * 2LL)) * cnt1 / 2LL % mod; 43 sum1 += (2LL + (2LL + (cnt2 - 1LL) * 2LL)) * cnt2 / 2LL % mod, sum1 %= mod; 44 cnt3 = (two[now1 + 1] - lt + 1) % mod; // 左区间开,去掉最后一项,注意求和的前提是cnt3>0 45 if(cnt3 > 0) sum1 -= (2LL * (2LL + (cnt2 - 1LL) * 2LL) - (cnt3 - 1LL) * 2LL) * cnt3 / 2LL % mod, sum1 = (sum1 + mod) % mod; 46 }else { // 2^{even} 47 cnt1 = two[now1] / 3 % mod; 48 cnt2 = 2LL * cnt1 % mod; 49 sum1 = (1LL + (1LL + (cnt1 - 1LL) * 2LL)) * cnt1 / 2LL % mod; 50 sum1 += (2LL + (2LL + (cnt2 - 1LL) * 2LL)) * cnt2 / 2LL % mod, sum1 %= mod; 51 cnt3 = (lt - two[now1] - 1) % mod; // 左区间开,去掉最后一项,注意求和的前提是cnt3>0 52 if(cnt3 > 0) sum1 += (2LL * (1LL + cnt1 * 2LL) + 2LL * (cnt3 - 1LL)) * cnt3 / 2, sum1 %= mod; 53 } 54 if(now2 & 1) { // 2^{odd} 55 cnt1 = two[now2 + 1] / 3 % mod; 56 cnt2 = 2LL * cnt1 % mod; 57 sum2 = (1LL + (1LL + (cnt1 - 1LL) * 2LL)) * cnt1 / 2LL % mod; 58 sum2 += (2LL + (2LL + (cnt2 - 1LL) * 2LL)) * cnt2 / 2LL % mod, sum2 %= mod; 59 cnt3 = (two[now2 + 1] - rt) % mod; // 右区间闭,注意求和的前提是cnt3>0 60 if(cnt3 > 0) sum2 -= (2LL * (2LL + (cnt2 - 1LL) * 2LL) - (cnt3 - 1LL) * 2LL) * cnt3 / 2LL % mod, sum2 = (sum2 + mod) % mod; 61 }else { // 2^{even} 62 cnt1 = two[now2] / 3 % mod; 63 cnt2 = 2LL * cnt1 % mod; 64 sum2 = (1LL + (1LL + (cnt1 - 1LL) * 2LL)) * cnt1 / 2LL % mod; 65 sum2 += (2LL + (2LL + (cnt2 - 1LL) * 2LL)) * cnt2 / 2LL % mod, sum2 %= mod; 66 cnt3 = (rt - two[now2]) % mod; // 右区间闭,注意求和的前提是cnt3>0 67 if(cnt3 > 0) sum2 += (2LL * (1LL + cnt1 * 2LL) + 2LL * (cnt3 - 1LL)) * cnt3 / 2 % mod, sum2 %= mod; 68 } 69 cout << (sum2 - sum1 + mod) % mod << endl; 70 } 71 return 0; 72 }
D、Stas and the Queue at the Buffet
思路:简单数学。将 $ a_i \cdot (j-1) + b_i \cdot (n-j) $ 式子展开化简得 $ (a_i - b_i) \cdot j + b_i \cdot n - a_i $,可以发现此式子只和j有关,那么问题就变得非常简单了,根据排序不等式的性质可知只需逆序配对即可!
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <iomanip> 8 #include <complex> 9 #include <string> 10 #include <vector> 11 #include <set> 12 #include <map> 13 #include <list> 14 #include <deque> 15 #include <queue> 16 #include <stack> 17 #include <bitset> 18 using namespace std; 19 typedef long long LL; 20 typedef unsigned long long ULL; 21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左 22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向 23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 24 const double eps = 1e-6; 25 const double PI = acos(-1.0); 26 const int maxn = 1e5+5; 27 const int inf = 0x3f3f3f3f; 28 29 LL n, a, b, ans, c[maxn]; 30 31 int main() { 32 while(cin >> n) { 33 ans = 0LL; 34 for(LL i = 1; i <= n; ++i) cin >> a >> b, c[i] = a - b, ans += b * n - a; 35 sort(c + 1, c + n + 1, greater<LL>()); 36 for(LL i = 1; i <= n; ++i) ans += c[i] * i; 37 cout << ans << endl; 38 } 39 return 0; 40 }