Codeforces Global Round 14
A
sb题
判断一下和是不是x就行了
4mins才写完,手速下降严重啊!!
code:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n, m, t, a[N];
int main() {
scanf("%d", &t);
while(t --) {
scanf("%d%d", &n, &m);
int s = 0;
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), s += a[i];
if(s == m) {
printf("NO\n");
continue;
}
s = 0;
printf("YES\n");
for(int i = 1; i <= n; i ++) {
if(s + a[i] == m) swap(a[i], a[n]);
s += a[i];
printf("%d ", a[i]);
} printf("\n");
}
return 0;
}
B
这题竟然是我卡的最久的题
想了一年
发现可以直接考虑面积是不是完全平方数
降至严重
code:
#include<bits/stdc++.h>
using namespace std;
int check(int n) {
if(!n) return 0;
int m = sqrt(n);
return m * m == n;
}
int n, t;
int main() {
scanf("%d", &t);
while(t --) {
scanf("%d", &n);
if(n & 1) {
printf("NO\n");
continue;
}
if(check(n / 2) || (n % 4 == 0 && check(n / 4))) printf("YES\n");
else printf("NO\n");
}
return 0;
}
C
也是道简单题
维护m个数
从1到n考虑,对于每个 i,每次把m个数中最小的那个数加上a[i]
然后判断即可
code:
#include<bits/stdc++.h>
#define N 200005
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
int a[N], n, m, x, ans[N];
int main() {
int t;
scanf("%d", &t);
while(t --) {
scanf("%d%d%d", &n, &m, &x);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), ans[i] = 0;
while(q.size()) q.pop();
for(int i = 1; i <= m; i ++) q.push(make_pair(a[i], i)), ans[i] = i;//, printf("** %d %d\n", a[i], i);
for(int i = m + 1; i <= n; i ++) {
int s = q.top().first, id = q.top().second; q.pop();
// printf(" %d %d\n", s, id);
ans[i] = id; s += a[i];
q.push(make_pair(s, id));
}
int ha = q.top().first, f = 0;
// printf("%d\n", ha);
while(q.size()) {
if(q.top().first - ha > x) {
f = 1;
break;
}
q.pop();
}
if(f) {
printf("NO\n");
continue;
}
printf("YES\n");
for(int i = 1; i <= n; i ++) printf("%d ", ans[i]); printf("\n");
}
return 0;
}
D
sb贪心
直接看代码吧
code:
#include<bits/stdc++.h>
#define N 400005
using namespace std;
int t, n, n1, n2, ha1[N], ha2[N];
int main() {
scanf("%d", &t);
while(t --) {
scanf("%d%d%d", &n, &n1, &n2);
for(int i = 1, x; i <= n1; i ++) scanf("%d", &x), ha1[x] ++;
for(int i = 1, x; i <= n2; i ++) scanf("%d", &x), ha2[x] ++;
if(n1 > n2) for(int i = 0; i <= n; i ++) swap(ha1[i], ha2[i]), swap(n1, n2);
for(int i = 1; i <= n; i ++) {
int x = min(ha1[i], ha2[i]);
ha1[i] -= x, ha2[i] -= x;
}
int ans = 0;
for(int i = 1; i <= n; i ++) ans += ha1[i];
int s = n / 2 - n1;
for(int i = 1; i <= n; i ++) {
while(s && ha2[i] >= 2) ans ++, s --, ha2[i] -= 2;
}
ans += s * 2;
printf("%d\n", ans);
for(int i = 0; i <= n; i ++) ha1[i] = ha2[i] = 0;
}
return 0;
}
E
一开始设了个四维状态的DP,
O
(
n
4
)
O(n^4)
O(n4)很蠢
到结束都没有想出来怎么优化
看题解后发现自己DP像cxk
最后的序列肯定是连续一段手动开的,一个自动开的,连续一段手动开的……
所以可以按照这个分段来DP
设
f
[
i
]
[
j
]
表
示
目
前
已
经
有
i
个
开
了
,
最
后
一
个
是
自
动
开
的
,
手
动
开
了
j
个
的
方
案
数
设f[i][j]表示目前已经有i个开了,最后一个是自动开的,手动开了j个的方案数
设f[i][j]表示目前已经有i个开了,最后一个是自动开的,手动开了j个的方案数
dp就无脑冲就行了
code:
#include<bits/stdc++.h>
#define N 805
#define ll long long
using namespace std;
int n, mod, c[N][N], mi[N];
ll f[N][N];
int main() {
scanf("%d%d", &n, &mod);
for(int i = 0; i <= n; i ++) c[i][0] = c[i][i] = 1;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= i; j ++)
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
mi[0] = 1;
for(int i = 1; i <= n; i ++) mi[i] = mi[i - 1] * 2 % mod;
f[0][0] = 1;
for(int i = 0; i <= n; i ++)
for(int j = 0; j <= i; j ++)
for(int k = 1; k + i <= n; k ++)
(f[i + k + 1][j + k] += f[i][j] * mi[k - 1] % mod * c[j + k][k]) %= mod;
ll ans = 0;
for(int i = 0; i <= n; i ++) ans = (ans + f[n + 1][i]) % mod;
printf("%lld", ans);
return 0;
}