emmmm......ouuan大佬上紫了,我却没打......
首先吐槽一波家长会和机房锁门,害我只能来打虚拟赛。
写了abcd四题,还是被ouuan大佬吊打.......
264名,应该能上分吧。
A,你要做n张贺卡,每张贺卡需要2红,5黄,8蓝。
你买一张卡纸就能获得k个某种颜色。问最少买几张卡纸。
解:红色就是(2*n-1)/k+1,别的以此类推。
B,给你个数列,ai=i*(-1)^i,求L到R的和。
解:我们先两两求和,最后可能有多出来的,处理一下。
C,给你个n*m的矩阵,黑白染色。先把一块染成白色,又把一块染成黑色。求最终的黑色个数。
解:先分开处理,然后把交叉的地方的黑色加上。
D,题意比较复杂......
可以想到一种贪心就是先尽量切边缘的一条小道,直到剩余刀数不够。
然后判断别的地方空出来的能不能放下所有剩余刀数。
转化一下就是把别的地方都切了,看刀数是不是小于k。
再转化,能容纳的总刀数 - 切出来小道后小道内不能切的刀数 < k 即为不合法。
发现当n较大时,如果这个图能够容纳k刀,一定存在方案。
n比较小的时候就用公式计算。
#include <bits/stdc++.h> typedef long long LL;
const int N = ; LL n, k; inline bool check(LL n, LL k) {
if(!n) {
return k == ;
}
k = * k + ;
LL a = ;
for(int i = ; i <= n; i++) {
a *= ;
if(a >= k) {
return ;
}
}
return ;
} inline LL qpow(LL a, LL b) {
LL ans = ;
while(b) {
if(b & ) {
ans *= a;
}
a *= a;
b = b >> ;
}
return ans;
} inline void solve() { scanf("%lld%lld", &n, &k); if(!check(n, k)) {
printf("NO\n");
return;
} LL t = ;
while((1ll << (t + )) - (t + ) <= k && t < n) {
t++;
}
//k -= (1ll << (t + 2)) - (t + 3));
LL x = n - t;
if(n <= ) {
LL temp = (qpow(, n) - ) - (qpow(, t + ) - ) * (qpow(, x) - );
k *= ;
if(k <= temp) {
printf("YES %d\n", x);
}
else {
printf("NO\n");
}
return;
}
printf("YES %d\n", x);
return;
} int main() { int T;
scanf("%d", &T);
while(T--) {
solve();
} return ;
}
AC代码
看了看E,好神仙啊,完全不知道如何操作......
给你个字母矩阵,问有多少个子矩阵满足:可以只交换行内元素,使得这个子矩阵的每行每列都回文。n,m<=250
回来补票了。
先看一个合法的子矩阵有什么性质。首先每行出现奇数次的元素不能超过1。然后对应行必须所有字母出现次数相同。
首先预处理出后一个限制。然后枚举子矩阵的左右边界,进行manacher。
#include <bits/stdc++.h> typedef unsigned long long uLL;
typedef long long LL;
const int N = ;
const uLL B = ; uLL h[N * ][N][N], pw[];
int n, m, bin[], f[N * ];
char s[N * ][N];
std::bitset<N> valid[N * ][N]; int main() { scanf("%d%d", &n, &m);
n = n * - ;
for(int i = ; i <= n; i += ) {
scanf("%s", s[i] + );
}
pw[] = ;
for(int i = ; i <= ; i++) {
pw[i] = pw[i - ] * B;
} /// prework
for(int i = ; i <= n; i += ) {
for(int l = ; l <= m; l++) {
memset(bin, , sizeof(bin));
int cnt = ;
uLL H = ;
for(int r = l; r <= m; r++) {
/// [l, r] add r
valid[i + ][l][r] = ;
if(i == ) valid[i - ][l][r] = ;
int f = s[i][r] - 'a';
bin[f]++;
//printf("%llu + %llu = ", H, pw[f]);
H += pw[f];
//printf("%llu \n", H);
if(bin[f] & ) {
cnt++;
}
else {
cnt--;
}
if(cnt <= ) {
valid[i][l][r] = ;
h[i][l][r] = H;
}
//printf("%d %d %d = %d %llu \n", i, l, r, (int)(valid[i][l][r]), h[i][l][r]);
}
}
} LL ans = ;
for(int l = ; l <= m; l++) {
for(int r = l; r <= m; r++) {
/// [l, r]
int large = , pos = ;
//printf("> > [%d %d] \n", l, r);
for(int i = ; i <= n + ; i++) {
if(!valid[i][l][r]) {
f[i] = ;
pos = ;
large = ;
continue;
}
if(i > large) {
f[i] = ;
int j = ;
while(i - j >= && i + j <= n + && h[i - j][l][r] == h[i + j][l][r] && valid[i - j][l][r] && valid[i + j][l][r]) {
f[i] = j;
j++;
}
pos = i;
large = i + f[i];
}
else {
f[i] = f[ * pos - i];
if(i + f[i] > large) {
f[i] = large - i;
}
int j = f[i] + ;
while(i - j >= && i + j <= n + && h[i - j][l][r] == h[i + j][l][r] && valid[i - j][l][r] && valid[i + j][l][r]) {
f[i] = j;
j++;
}
if(i + f[i] > large) {
large = i + f[i];
pos = i;
}
}
ans += (f[i] + ) / ;
//printf("f %d = %d ans += %d \n", i, f[i], (f[i] + 1) / 2);
}
}
} printf("%lld\n", ans);
return ;
}
AC代码