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
");
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
", x);
55         }
56         else {
57             printf("NO
");
58         }
59         return;
60     }
61     printf("YES %d
", 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 }
AC代码

看了看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 
", 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 
", 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] 
", 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 
", i, f[i], (f[i] + 1) / 2);
 95             }
 96         }
 97     }
 98 
 99     printf("%lld
", ans);
100     return 0;
101 }
AC代码
原文地址:https://www.cnblogs.com/huyufeifei/p/10017157.html