AtCoder Beginner Contest 313
A - To Be Saikyo
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
int n;
cin >> n;
vector<int> a(n);
for( auto & i : a ) cin >> i;
cout << max( 0 , *max_element( a.begin()+1 , a.end() ) + 1 - a.front() )<< "\n";
return 0;
}
B - Who is Saikyo?
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
int n , m;
cin >> n >> m;
vector<int> f( n+1 , 1 );
for( int x , y ; m ; m -- )
cin >> x >> y ,f[y] = 0;
int res = -2;
for( int i = 1 ; i <= n ; i ++ ){
if( f[i] == 1 ){
if( res == -2 ) res = i;
else res = -1;
}
}
if( res == -2 ) res = -1;
cout << res << "\n";
return 0;
}
C - Approximate Equalization 2
先把期望的序列求出来,然后两个序列分别排序作差即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main(){
ios::sync_with_stdio(0),cin.tie(0);
int n;
cin >> n;
int cnt = 0;
vector<int> a(n);
for( auto & i : a ) cin >> i , cnt += i;
sort( a.begin() , a.end() );
vector<int> b(n , cnt / n );
cnt = cnt % n;
for( int i = 0 ; i < cnt ; i ++ ) b[i] ++;
reverse( b.begin() , b.end() );
int res = 0;
for( int i = 0 ; i < n ; i ++ )
if( a[i] > b[i] ) res += a[i] - b[i];
cout << res << "\n";
return 0;
}
D - Odd or Even
这里回答的是子序列的奇偶性实际上就是异或和。
如果两个子序列的只有一个数不同,那么两个子序列异或和的异或等价这两个不同的数的异或。
所以我们可以推出\([2,k]\)中每个数的与\(1\)的异或,在结合\([1,k]\)的异或和就能推出\([1,k]\)的值。
然后再计算\(i\)与\(i+k\)的异或,进而推出整个序列。
当然询问的方法有很多。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int32_t main() {
int n, k;
cin >> n >> k;
auto q = [](int l, int r, int x) {
vector<int> v;
for (int i = l; i <= r; i++)
if (i != x) v.push_back(i);
return v;
};
auto query = [](const vector<int> &v) {
cout << "?";
for (auto i: v)
cout << " " << i;
cout << endl << flush;
};
map<vector<int>, int> mp;
for (int i = 1, t; i <= k; i++) {
auto v = q(1, k + 1, i);
query(v);
cin >> t;
mp[v] = t;
}
for (int i = 1, t; i <= n - k + 1; i++) {
auto v = q(i, i + k - 1, 0);
if (mp.count(v) > 0) continue;
query(v);
cin >> t;
mp[v] = t;
}
int T1 = mp[q(1, k + 1, 1)];
int cnt = 1;
for (int i = 2; i <= k; i++)
cnt += (T1 == mp[q(1, k + 1, i)]);
vector<int> a(n + 1);
a[1] = (mp[q(1, k, 0)] == (cnt & 1));
for (int i = 2; i <= k; i++) {
if (T1 == mp[q(1, k + 1, i)]) a[i] = a[1];
else a[i] = !a[1];
}
for (int i = 1; i <= n - k; i++) {
if (mp[q(i, i + k - 1, 0)] == mp[q(i + 1, i + k, 0)]) a[i+k] = a[i];
else a[i+k] = !a[i];
}
cout << "!";
for( int i = 1 ; i <= n ; i ++ )
cout << " " << a[i];
cout << endl << flush;
return 0;
}
E - Duplicate
先考虑\(-1\)的情况,如果任意两个相邻的数都不为 1 那么这个地方就可以无限延长,答案就是\(-1\)
然后我们考虑倒序统计答案\(res\),对于当前的字符他每次被复制了\(s[i+1]-1\)个,一共复制了\(res\)次加上原本的\(1\)个,所以我们需要\(res\times(s[i+1]-1)+1\)次才可以把他完全删除掉。为什么是这个式子?因为能够被复制的数字只有\(1\)所以被复制的数字不会自己复制自己。
要注意的是,最后一个数字不需要删除,所以最后的答案还要减 1
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int32_t main(){
ios::sync_with_stdio(0),cin.tie(0);
int n;
string s;
cin >> n >> s;
for( int i = 1 ; i < n ; i ++ )
if( s[i] != '1' && s[i-1] != '1' )
cout << -1 , exit(0);
int res = 1;
for( int i = n-2 ; i >= 0 ; i -- ){
res = ( res + 1 + res * ( s[i+1] - '1' ) % mod ) % mod;
}
cout << res - 1 << "\n";
return 0;
}