CF1080
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比较小的时候就用公式计算。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 100010; 5 6 LL n, k; 7 8 inline bool check(LL n, LL k) { 9 if(!n) { 10 return k == 0; 11 } 12 k = 3 * k + 1; 13 LL a = 1; 14 for(int i = 1; i <= n; i++) { 15 a *= 4; 16 if(a >= k) { 17 return 1; 18 } 19 } 20 return 0; 21 } 22 23 inline LL qpow(LL a, LL b) { 24 LL ans = 1; 25 while(b) { 26 if(b & 1) { 27 ans *= a; 28 } 29 a *= a; 30 b = b >> 1; 31 } 32 return ans; 33 } 34 35 inline void solve() { 36 37 scanf("%lld%lld", &n, &k); 38 39 if(!check(n, k)) { 40 printf("NO\n"); 41 return; 42 } 43 44 LL t = 0; 45 while((1ll << (t + 2)) - (t + 3) <= k && t < n) { 46 t++; 47 } 48 //k -= (1ll << (t + 2)) - (t + 3)); 49 LL x = n - t; 50 if(n <= 7) { 51 LL temp = (qpow(4, n) - 1) - (qpow(2, t + 1) - 1) * (qpow(4, x) - 1); 52 k *= 3; 53 if(k <= temp) { 54 printf("YES %d\n", x); 55 } 56 else { 57 printf("NO\n"); 58 } 59 return; 60 } 61 printf("YES %d\n", x); 62 return; 63 } 64 65 int main() { 66 67 int T; 68 scanf("%d", &T); 69 while(T--) { 70 solve(); 71 } 72 73 return 0; 74 }
看了看E,好神仙啊,完全不知道如何操作......
给你个字母矩阵,问有多少个子矩阵满足:可以只交换行内元素,使得这个子矩阵的每行每列都回文。n,m<=250
回来补票了。
先看一个合法的子矩阵有什么性质。首先每行出现奇数次的元素不能超过1。然后对应行必须所有字母出现次数相同。
首先预处理出后一个限制。然后枚举子矩阵的左右边界,进行manacher。
1 #include <bits/stdc++.h> 2 3 typedef unsigned long long uLL; 4 typedef long long LL; 5 const int N = 252; 6 const uLL B = 13331; 7 8 uLL h[N * 2][N][N], pw[31]; 9 int n, m, bin[26], f[N * 2]; 10 char s[N * 2][N]; 11 std::bitset<N> valid[N * 2][N]; 12 13 int main() { 14 15 scanf("%d%d", &n, &m); 16 n = n * 2 - 1; 17 for(int i = 1; i <= n; i += 2) { 18 scanf("%s", s[i] + 1); 19 } 20 pw[0] = 1; 21 for(int i = 1; i <= 30; i++) { 22 pw[i] = pw[i - 1] * B; 23 } 24 25 /// prework 26 for(int i = 1; i <= n; i += 2) { 27 for(int l = 1; l <= m; l++) { 28 memset(bin, 0, sizeof(bin)); 29 int cnt = 0; 30 uLL H = 0; 31 for(int r = l; r <= m; r++) { 32 /// [l, r] add r 33 valid[i + 1][l][r] = 1; 34 if(i == 1) valid[i - 1][l][r] = 1; 35 int f = s[i][r] - 'a'; 36 bin[f]++; 37 //printf("%llu + %llu = ", H, pw[f]); 38 H += pw[f]; 39 //printf("%llu \n", H); 40 if(bin[f] & 1) { 41 cnt++; 42 } 43 else { 44 cnt--; 45 } 46 if(cnt <= 1) { 47 valid[i][l][r] = 1; 48 h[i][l][r] = H; 49 } 50 //printf("%d %d %d = %d %llu \n", i, l, r, (int)(valid[i][l][r]), h[i][l][r]); 51 } 52 } 53 } 54 55 LL ans = 0; 56 for(int l = 1; l <= m; l++) { 57 for(int r = l; r <= m; r++) { 58 /// [l, r] 59 int large = 0, pos = 0; 60 //printf("> > [%d %d] \n", l, r); 61 for(int i = 0; i <= n + 1; i++) { 62 if(!valid[i][l][r]) { 63 f[i] = 0; 64 pos = 0; 65 large = 0; 66 continue; 67 } 68 if(i > large) { 69 f[i] = 0; 70 int j = 1; 71 while(i - j >= 0 && i + j <= n + 1 && h[i - j][l][r] == h[i + j][l][r] && valid[i - j][l][r] && valid[i + j][l][r]) { 72 f[i] = j; 73 j++; 74 } 75 pos = i; 76 large = i + f[i]; 77 } 78 else { 79 f[i] = f[2 * pos - i]; 80 if(i + f[i] > large) { 81 f[i] = large - i; 82 } 83 int j = f[i] + 1; 84 while(i - j >= 0 && i + j <= n + 1 && h[i - j][l][r] == h[i + j][l][r] && valid[i - j][l][r] && valid[i + j][l][r]) { 85 f[i] = j; 86 j++; 87 } 88 if(i + f[i] > large) { 89 large = i + f[i]; 90 pos = i; 91 } 92 } 93 ans += (f[i] + 1) / 2; 94 //printf("f %d = %d ans += %d \n", i, f[i], (f[i] + 1) / 2); 95 } 96 } 97 } 98 99 printf("%lld\n", ans); 100 return 0; 101 }