Educational Codeforces Round 120 (Rated for Div. 2)
Educational Codeforces Round 120 (Rated for Div. 2)
A. Construct a Rectangle
题意:三根木棍,长度abc,要选一根木棍截成两段,长度不限不能为空必须为整数,问最后四根木棍是否能成矩形
最长的木棍是两个短的的和 ; 有两个木棍长度相等,剩下一个长度是偶数;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
signed main() {
int T;
cin >> T;
while (T--) {
int a[3];
cin >> a[0] >> a[1] >> a[2];
sort(a, a + 3);
if (a[2] == a[0] + a[1]) {
cout << "YES" << endl;
continue;
}
if (a[0] == a[1] && a[2] % 2 == 0) {
cout << "YES" << endl;
continue;
}
if (a[1] == a[2] && a[0] % 2 == 0) {
cout << "YES" << endl;
continue;
}
cout << "NO" << endl;
}
}
B. Berland Music
题意:有很多首歌,每首歌本身有个评分,这些评分形成一个n的排列,现在需要重新打分,会给出喜欢/不喜欢这些歌,不喜欢的歌的评分一定比喜欢的低,要求新的分数也成排列,且使得 ∑ ∣ n e w i − o l d i ∣ \sum|new_i - old_i| ∑∣newi−oldi∣ 最小,给出新排列
按喜欢不喜欢为第一关键字,旧评分为第二关键字排序,然后标分数,按序号排回来
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
struct node {
int id, p, q, s;
};
node mp[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> mp[i].p;
string s;
cin >> s;
for (int i = 1; i <= n; ++i) {
mp[i].id = i;
mp[i].s = s[i - 1] - '0';
}
sort(mp + 1, mp + n + 1, [&](node x, node y) {
if (x.s != y.s) return x.s < y.s;
return x.p < y.p;
});
for (int i = 1; i <= n; ++i) {
mp[i].q = i;
}
sort(mp + 1, mp + n + 1, [&](node x, node y) {
return x.id < y.id;
});
for (int i = 1; i <= n; ++i) {
cout << mp[i].q << " ";
}
cout << endl;
}
return 0;
}
C. Set or Decrease
题意:有一个数列,一次操作是将一个数-1,或将一个数变为已有的另一个数,问至少多少次操作后所有数的和小于k,数字可以为负
第二种操作(将一个数变成另一个数)肯定是把大的变成当前最小的数,
则减也减在当前最小的数上,最后再都变成它是最优的
枚举最大的多少个数会通过一次操作变成最小这个数
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 10;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll a[N], pre[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
ll T;
cin >> T;
while (T--) {
ll n, k;
cin >> n >> k;
for (ll i = 1; i <= n; ++i) cin >> a[i];
sort(a + 1, a + n + 1, [&](ll x, ll y) {
return x < y;
});
for (ll i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + a[i];
}
// ll mn = a[n];
// ll cnt = 1;
ll ans = inf;
for (ll i = 0; i < n; ++i) {
ll tmp = i;
ll need = k - (pre[n - i] - pre[1]) -a[1] * (i + 1);
tmp += max(0ll, (-need+ i) / (i + 1));
// cerr << need <<" "<<tmp << endl;
ans = min(tmp, ans);
}
cout << ans << endl;
}
return 0;
}
D. Shuffle
题意:给一个01串,可以选任意恰好包含k个1的子串重排,问能生成多少不同的串
刚开始在想把每个子串扣出来算贡献,但发现会有重复计算
可以固定最先和最后变动的位置,中间可随意排列,即选择题要求的子串的子串进行计数
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 5010;
const ll M = 1e5 + 10;
const ll mod = 998244353;
char s[N];
ll pre[N], fac[M], invfac[M];
ll qpow(ll x, ll n) {
ll res = 1;
while (n) {
if (n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
inline void init() {
fac[0] = 1, invfac[0] = 1;
for (ll i = 1; i < (int) (1e5); ++i) {
fac[i] = fac[i - 1] * i % mod;
invfac[i] = qpow(fac[i], mod - 2);
}
}
ll C(ll down, ll up) {
if(up == 0) return 1;
ll res = 1;
res = res * fac[down] % mod * invfac[down - up] % mod * invfac[up] % mod;
return res;
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
init();
ll n, k;
cin >> n >> k;
cin >> (s + 1);
for (ll i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + (s[i] - '0');
}
ll ans = 1;
for (ll i = 1; i <= n; ++i) {
for (ll j = i + 1; j <= n; ++j) {
if (pre[j] - pre[i - 1] > k || pre[n] < k) continue;
ll cnt0 = j - i + 1 - (pre[j] - pre[i - 1]), cnt1 = pre[j] - pre[i - 1];
if (s[i] == '0') cnt1--;
else cnt0--;
if (s[j] == '0') cnt1--;
else cnt0--;
ans = (ans + C(cnt0 + cnt1, cnt0)) % mod;
}
}
cout << ans << endl;
}
E. Math Test
题意:n个学生m道题,对于每个学生每道题的做题情况给出,1表示正确0表示不正确,每个学生有一个预估的分数,m道题的分数从1到m构成一个m的排列,问成什么排列的时候
∑
n
o
w
i
−
e
x
p
e
c
t
i
\sum now_i - expect_i
∑nowi−expecti 最大
枚举每个学生的得分最后是否达到预估的状态(1表示大于等于预估分数
对于每个得分高于预估分的学生答对的题尽量给予高分值,对于每个最后得分低于预估分的学生答对的题给予低分值
对于每个状态统计每道题被答对的情况(被高于预估分的还是低于的)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e4 + 10;
const int inf = 0x3f3f3f3f;
int expect[15], ans[N], tmpans[N];
int res;
char s[15][N];
int tmp[15];
int n, m;
struct node {
int id, cnt, val;
int num;
//标号, 1的数量, 权重
//值
};
node mp[N];
inline void check() {
for (int i = 1; i <= m; ++i) {
mp[i].id = i;
mp[i].val = 0;
mp[i].cnt = 0;
}
for (int j = 1; j <= m; ++j) {
// mp[j].id = j;
for (int i = 0; i < n; ++i) {
if (s[i][j] == '1') {
if (tmp[i]) mp[j].val++, mp[j].cnt++;
else mp[j].val--;
}
}
}
sort(mp + 1, mp + m + 1, [&](node x, node y) {
if (x.val != y.val) return x.val < y.val;
return x.cnt < y.cnt;
});
for (int i = 1; i <= m; ++i) mp[i].num = i;
sort(mp + 1, mp + m + 1, [&](node x, node y) {
return x.id < y.id;
});
for (int i = 1; i <= m; ++i) tmpans[i] = mp[i].num;
int tmptot = 0, tmps[15] = {0};
for (int i = 0; i < n; ++i) {
for (int j = 1; j <= m; ++j) {
if (s[i][j] == '1') tmps[i] += tmpans[j];
}
}
for (int i = 0; i < n; ++i) {
tmptot += abs(tmps[i] - expect[i]);
}
if (tmptot >= res) {
res = tmptot;
for (int i = 1; i <= m; ++i) ans[i] = tmpans[i];
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int T;
cin >> T;
while (T--) {
res = -1;
cin >> n >> m;
for (int i = 0; i < n; ++i) cin >> expect[i];
for (int i = 0; i < n; ++i) cin >> (s[i] + 1);
for (int st = 0; st < (1 << n); ++st) {
for (int i = 0; i < n; ++i) {
tmp[i] = (st >> i) & 1;
}
check();
}
for (int i = 1; i <= m; ++i) cout << ans[i] << " ";
cout << endl;
}
}
F. Quadratic Set
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll N = 1e6 + 10;
ll primes[N], cnt = 0;
bool st[N];
ll h[N], hi[N];
// hash[i] hash[i!]
mt19937_64 rnd(time(nullptr));
void sieve() {
cnt = 0;
for (ll i = 2; i < N; ++i) {
if (!st[i]) {
primes[++cnt] = i;
h[i] = rnd();
}
for (ll j = 1; primes[j] * i < N; ++j) {
st[primes[j] * i] = 1;
if (i % primes[j] == 0) break;
}
}
}
vector<pair<ll, ll> > fac(ll n) {
vector<pair<ll, ll> > res;
for (ll i = 1; primes[i] <= n / primes[i]; ++i) {
if (n % primes[i] == 0) {
pair<ll, ll> tt;
tt.first = primes[i];
ll num = 0;
while (n % primes[i] == 0) {
num++;
n /= primes[i];
}
tt.second = num;
res.push_back(tt);
}
}
if (n != 1) {
res.push_back({n, 1});
}
return res;
}
map<ll, ll> mp;
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
memset(h, -1, sizeof h);
h[0] = h[1] = 0;
sieve();
ll n;
cin >> n;
for (ll i = 1; i <= n; ++i) {
if (h[i] == -1) {
vector<pair<ll, ll> > tmp = fac(i);
h[i] = 0;
for (auto tt : tmp) {
if (tt.second & 1) {
h[i] = h[i] ^ h[tt.first];
}
}
}
hi[i] = hi[i - 1] ^ h[i];
mp[hi[i]] = i;
}
ll fp = 0;
for (ll i = 1; i <= n; ++i) fp = fp ^ hi[i];
// case 1
if (fp == 0) {
cout << n << endl;
for (ll i = 1; i <= n; ++i) {
cout << i << " ";
}
return 0;
}
//case 2
for (ll i = 1; i <= n; ++i) {
if ((fp ^ hi[i]) == 0) {
cout << n - 1 << endl;
for (ll j = 1; j <= n; ++j) {
if (j == i) continue;
cout << j << " ";
}
return 0;
}
}
//case 3
for (ll i = 1; i <= n; ++i) {
if (mp.count(fp ^ hi[i])) {
ll mm = mp[fp ^ hi[i]];
cout << n - 2 << endl;
for (ll j = 1; j <= n; ++j) {
if (j == i || j == mm) continue;
cout << j << " ";
}
return 0;
}
}
// case 4
cout << n - 3 << endl;
for (ll i = 1; i <= n; ++i) {
if (i == 2 || i == ((n - 1) / 2) || i == n) continue;
cout << i << " ";
}
return 0;
}