比赛链接:https://codeforces.ml/contest/1582
A. Luntik and Concerts 直接找规律,发现答案肯定只有01。
模上1,2,3的公倍数,然后暴力枚举
(a+c)%2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 3e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) #define endl '\n' void solve () { int T; cin >> T; while (T--) { int a, b, c; cin >> a >> b >> c; cout << (a+c)%2 << endl; } } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
B. Luntik and Subsequences 记0的个数为num0,1的个数为num1
$f=num1*2^{num0}$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 2e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) void solve () { int T; cin >> T; while (T--) { int n; cin >> n; vector<int > a (n+1 ) ; ll base = 1 , ans = 0 ; for (int i = 1 ; i <= n; i++) { cin >> a[i]; if (a[i] == 0 ) base = base * 2 ; } for (int i = 1 ; i <= n; i++) { if (a[i] == 1 ) ans += base; } cout << ans << endl; } } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
C. Grandma Capa Knits a Scarf 从两端开始枚举,直到第一个不同位置,那么答案一定就是两者之一了,暴力判断一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 2e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) void solve () { int T; cin >> T; while (T--) { int n; cin >> n; string s; cin >> s; char c1, c2; int flag = 0 ; for (int i = 0 ; i < s.size () / 2 ; i++) { if (s[i] != s[n-i-1 ]) { flag = 1 ; c1 = s[i]; c2 = s[n-i-1 ]; break ; } } if (!flag) cout << 0 << endl; else { int l = 0 , r = n - 1 ; int num1 = 0 ; int flag1 = 0 ; while (l < r) { if (s[l] == s[r]) { l++, r--; } else { if (s[l] == c1) { l++; num1++; } else if (s[r] == c1) { r--; num1++; } else { flag1 = 1 ; break ; } } } l = 0 , r = n - 1 ; int num2 = 0 ; int flag2 = 0 ; while (l < r) { if (s[l] == s[r]) { l++, r--; } else { if (s[l] == c2) { l++; num2++; } else if (s[r] == c2) { r--; num2++; } else { flag2 = 1 ; break ; } } } if (flag1 && flag2) cout << -1 << endl; else { if (flag1 && !flag2) cout << num2 << endl; else if (!flag1 && flag2) cout << num1 << endl; else cout << min (num1, num2) << endl; } } } } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
D. Vupsen, Pupsen and 0 思路其实很好想,如果是偶数,直接两两配对。如果是奇数,那么我们选择三个数配对,三个数怎么选呢,如果三个数分别为a,b,c,那么我们给a,b一个系数c,c的系数为-(a+b)。这里还有一个坑,即a+b为0。我先是随机找两个数判,然后t了,后来改成两个同符号的就可以了。
记得两两配对需要除上gcd,不然第二种情况$\sum bi$可能会大于1e9
以下是证明可行性: 奇数时的$\sum bi$最大可构造的数为1e4,1e4-1,1e4,1e4-1…,因此sum<1e9-1e5,那么剩下的a,b,c系数和肯定小于1e5,因此符合要求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 2e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) int a[N];void solve () { int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 1 ; i <= n; i++) cin >> a[i]; if (n % 2 == 0 ) { for (int i = 1 ; i <= n; i += 2 ) { cout << -a[i+1 ] << ' ' << a[i] << ' ' ; } cout << endl; } else { int x, y; vector<int > fu, zhen; for (int i = 1 ; i <= n; i++) { if (a[i] > 0 ) zhen.push_back (i); else fu.push_back (i); } if (fu.size () > 1 ) x = fu[0 ], y = fu[1 ]; else x = zhen[0 ], y = zhen[1 ]; vector<int > vis (n+1 ) , ans (n+1 ) ; vis[x] = vis[y] = 1 ; int pre = 0 ; for (int i = 1 ; i <= n; i ++) { if (vis[i]) continue ; if (pre) { int gcd = __gcd(abs (a[i]), abs (a[pre])); ans[i] = -a[pre]/gcd; ans[pre] = a[i]/gcd; vis[pre] = vis[i] = 1 ; pre = 0 ; } else { pre = i; } } for (int i = 1 ; i <= n; i++) { if (!vis[i]) { ans[x] = ans[y] = a[i]; ans[i] = -(a[x]+a[y]); break ; } } for (int i = 1 ; i <= n; i++) cout << ans[i] << ' ' ; cout << endl; } } } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
E. Pchelyonok and Segments 考虑dp,因为$\frac{(k+1)*k}{2}<n$,$k<\sqrt{(2n)}$
因此状态可以表示成$dp[i][j]$代表前i个数当前长度为j的最大值
$dp[i][j]=max(dp[i][j],sum[i+j-1]-sum[i-1])$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 1e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) int a[N];ll dp[N][500 ], sum[N]; void solve () { int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 0 ; i <= n+1 ; i++) { for (int j = 0 ; j <= sqrt (2 *n); j++) { dp[i][j] = 0 ; } } for (int i = 1 ; i <= n; i++) cin >> a[i], sum[i] = sum[i-1 ] + a[i]; dp[n+1 ][0 ] = inf; for (int i = n; i >= 1 ; i--) { for (int j = 0 ; j <= sqrt (2 *n); j++) { dp[i][j] = dp[i+1 ][j]; if (j && i + j - 1 <= n && sum[i+j-1 ] - sum[i-1 ] < dp[i+j][j-1 ]) { dp[i][j] = max (dp[i][j], sum[i+j-1 ] - sum[i-1 ]); } } } int ans = 0 ; for (int j = 1 ; j <= sqrt (2 *n); j++) { if (dp[1 ][j]) ans = j; } cout << ans << endl; } } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
F1. Korney Korneevich and XOR (easy version) 同样考虑dp
dp的状态还是很巧妙的,设$dp[i]$表示构成i的当前最小值,两层for转移一下就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 2e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) #define endl '\n' int a[N];int dp[N];void solve () { int n; cin >> n; for (int i = 1 ; i <= n; i++) cin >> a[i]; memset (dp, 0x3f , sizeof dp); dp[0 ] = 0 ; for (int i = 1 ; i <= n; i++) { for (int j = 0 ; j <= 1024 ; j++) { if (a[i] > dp[j]) { dp[j^a[i]] = min (dp[j^a[i]], a[i]); } } } vector<int > ans; for (int i = 0 ; i <= 1024 ; i++) if (dp[i] <= 500 ) ans.push_back (i); cout << ans.size () << endl; for (auto it : ans) cout << it << ' ' ; cout << endl; } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }
赛后想到更直接的转移,利用线段树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int , int > pii;typedef unsigned long long ull;const ll inf = 1e18 ;const int N = 2e5 + 10 ;const int M = 1e6 + 10 ;const double eps = 1e-8 ;const int mod = 1e9 + 7 ;#define fi first #define se second #define re register #define lowbit (-x&x) #define endl '\n' int a[N];struct Tree { int l, r; bitset<1024> f; }t[505 <<2 ]; void push_up (int u) { t[u].f = t[u<<1 ].f | t[u<<1 |1 ].f; } void build (int u, int l, int r) { t[u].l = l, t[u].r = r; if (l == r) { if (l == 0 ) t[u].f[0 ] = 1 ; return ; } int mid = (l + r) >> 1 ; build (u<<1 , l, mid); build (u<<1 |1 , mid+1 , r); push_up (u); } void modify (int u, int pos, bitset<1024 > val) { if (t[u].l == t[u].r) { t[u].f |= val; return ; } int mid = (t[u].l + t[u].r) >> 1 ; if (pos <= mid) modify (u<<1 , pos, val); else modify (u<<1 |1 , pos, val); push_up (u); } bitset<1024> query (int u, int ql, int qr) { if (ql <= t[u].l && qr >= t[u].r) return t[u].f; int mid = (t[u].l + t[u].r) >> 1 ; bitset<1024> ans; if (ql <= mid) ans |= query (u<<1 , ql, qr); if (qr > mid) ans |= query (u<<1 |1 , ql, qr); return ans; } void solve () { int n; cin >> n; for (int i = 1 ; i <= n; i++) cin >> a[i]; build (1 , 0 , 500 ); for (int i = 1 ; i <= n; i++) { if (!a[i]) continue ; bitset<1024> now = query (1 , 0 , a[i]-1 ); for (int j = 0 ; j < 1024 ; j++) if (now[j]) now[j^a[i]]=1 ; modify (1 , a[i], now); } cout << t[1 ].f.count () << endl; for (int i = 0 ; i < 1024 ; i++) if (t[1 ].f[i]) cout << i << ' ' ; cout << endl; } signed main () { ios_base::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifdef ACM_LOCAL freopen ("input" , "r" , stdin); freopen ("output" , "w" , stdout); #endif #ifdef ACM_LOCAL auto start = clock (); #endif int t = 1 ; while (t--) solve (); #ifdef ACM_LOCAL auto end = clock (); cerr << "Run Time: " << double (end - start) / CLOCKS_PER_SEC << "s" << endl; #endif return 0 ; }