T1 [JZOJ3229] 回文子序列

题目描述

  回文序列是指左右对称的序列。我们会给定一个N×M的矩阵,你需要从这个矩阵中找出一个P×P的子矩阵,使得这个子矩阵的每一列和每一行都是回文序列。

数据范围

  对于 $20\%$ 的数据,$1 \leq N,M \leq 10$

  对于 $100\%$ 的数据,$1 \leq N,M \leq 300$

分析

  $O(n^5)$ 暴力跑起来真实快

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. #define ll long long
  10. #define inf 0x3f3f3f3f
  11. #define N 305
  12.  
  13. int n, m, flag;
  14. int g[N][N];
  15.  
  16. int main() {
  17. scanf("%d%d", &n, &m);
  18. for (int i = ; i <= n; i++)
  19. for (int j = ; j <= m; j++)
  20. scanf("%d", &g[i][j]);
  21. for (int k = min(n, m); k; k--)
  22. for (int x = ; x + k - <= n; x++)
  23. for (int y = ; y + k - <= m; y++) {
  24. flag = ;
  25. for (int i = ; i < k; i++) {
  26. for (int j = ; j <= k / ; j++)
  27. if (g[x + i][y + j - ] != g[x + i][y + k - j] ||
  28. g[x + j - ][y + i] != g[x + k - j][y + i]) {
  29. flag = ; break;
  30. }
  31. if (!flag) break;
  32. }
  33. if (flag) {printf("%d", k); return ;}
  34. }
  35.  
  36. return ;
  37. }

T2 [JZOJ3230] 树环转换

题目描述

  给定一棵N个节点的树,去掉这棵树的一条边需要消耗值1,为这个图的两个点加上一条边也需要消耗值1。树的节点编号从1开始。在这个问题中,你需要使用最小的消耗值(加边和删边操作)将这棵树转化为环,不允许有重边。

  环的定义:(1)该图有N个点,N条边。(2)每个顶点的度数为2。(3)任意两点是可达的。

  树的定义:(1)该图有N个点,N-1条边。(2)任意两点是可达的。

数据范围

  对于 $20\%$ 的数据,$1 \leq N \leq 10$

  对于 $100\%$ 的数据,$1 \leq N \leq 10^6$

分析

  看到这种树状的题,很容易能想到树形 $dp$

  我们发现当环删去一条边时,就变成了一棵特殊的树——链

  所以考虑找出将树转化为一条链的最小代价,最后答案加一

  设 $f[x][0]$ 表示 $x$ 的子树转化为链且一个端点为 $x$ 时的最小代价,$f[x][1]$ 表示 $x$ 的子树转化为链(不考虑 $x$ 在链上的位置)的最小代价

  对于 $f[x][1]$,有两种转移方式

  

  令 $Sum$ 为 $\sum_{son} f[son][1]$,$Cnt$ 为 $x$ 的子节点数,则有 $$f[x][0]=min(Sum+2Cnt,Sum-(f[u][1]-f[u][0])+2(Cnt-1))$$

  对于 $f[x][0]$,$f[x][1]$ 当然属于其一种情况,此外还一种情况

  

  此时状态转移方程为 $$f[x][1]=min(f[x][0],Sum-(f[p][1]-f[p][0])-(f[q][1]-f[q][0])+2(Cnt-2))$$

  为了得到点 $x$ 的 $u,p,q$,只需要记录其子节点中 $f[son][1]-f[son][0]$ 的最大值与次大值

  由于数据对 $dfs$ 不是很友好,最后一个点会爆栈,所以我选择手写栈

  当然也可以选择 $bfs$ 或者贪心

  说到贪心,就是不停找两端点的度都大于 $2$ 的边删去,AC代码里跑得最快的是这么写的,感觉有点道理(然而这个贪心不存在完全正确性,结果会因遍历顺序产生不同)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. #define ll long long
  10. #define inf 0x3f3f3f3f
  11. #define N 1000005
  12.  
  13. int n, uu, vv, tot, top;
  14. int f[N][], stack[N], cur[N];
  15. int to[N << ], nxt[N << ], head[N];
  16.  
  17. inline void add(int u, int v) {
  18. to[++tot] = v; nxt[tot] = head[u]; head[u] = tot;
  19. }
  20.  
  21. void dfs() {
  22. memcpy(cur, head, sizeof cur);
  23. while (top) {
  24. int x = stack[top], go = ;
  25. for (int i = cur[x]; i; i = nxt[i])
  26. if (to[i] != stack[top - ]) {
  27. cur[x] = nxt[i]; stack[++top] = to[i];
  28. go = ; break;
  29. }
  30. if (go) continue;
  31. int m1 = -inf, m2 = -inf, sum = , cnt = ;
  32. for (int i = head[x]; i; i = nxt[i]) {
  33. if (to[i] == stack[top - ]) continue;
  34. int now = f[to[i]][] - f[to[i]][];
  35. if (now > m1) m2 = m1, m1 = now;
  36. else if (now > m2) m2 = now;
  37. sum += f[to[i]][]; cnt++;
  38. }
  39. if (cnt) {
  40. f[x][] = min(sum + * cnt, sum - m1 + * (cnt - ));
  41. f[x][] = min(f[x][], sum - m1 - m2 + * (cnt - ));
  42. }
  43. top--;
  44. }
  45. }
  46.  
  47. int main() {
  48. scanf("%d", &n);
  49. for (int i = ; i < n; i++) {
  50. scanf("%d%d", &uu, &vv);
  51. add(uu, vv); add(vv, uu);
  52. }
  53. stack[++top] = ; dfs();
  54. printf("%d", f[][] + );
  55.  
  56. return ;
  57. }

T3 [JZOJ3231] 海明距离

题目描述

  对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数。

  计算两个串之间的海明距离的时候,他们的长度必须相同。现在我们给出N个不同的二进制串,请计算出这些串两两之间的最短海明距离。

  (输入时每个二进制串用一个长度为5的16进制串表示)

数据范围

  对于 $30\%$ 的数据,$1 \leq N \leq 100$

  对于 $100\%$ 的数据,$1 \leq N \leq 10^5$

分析

  我们可以从小到大枚举海明距离,与该海明距离下的所有可能的异或结果

  对于一个异或结果,我们可以枚举给定的二进制串,如果该异或结果与该串异或后得到的二进制数也是一个给定的串,那么当前的海明距离是存在的,就可以直接得出答案

  这样做的理论时间复杂度为 $O(20 \times 2^{20}n)$,但实际上不可能同时达到 $ans=20$,$n=10^5$,因为这些二进制串两两之间互不相同,当 $ans=20$ 时,$n$ 一定为 $2$,以此类推,这个时间复杂度是远远跑不满的

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <queue>
  7. using namespace std;
  8. #define ll long long
  9. #define inf 0x3f3f3f3f
  10. #define N 100005
  11. #define M (1 << 20) + 5
  12.  
  13. int t, n, ans;
  14. int a[N], book[M], cnt[M];
  15. char c;
  16.  
  17. int main() {
  18. scanf("%d", &t);
  19. for (int i = , j = i; i < ( << ); j = ++i)
  20. while (j) j &= (j - ), cnt[i]++;
  21. while (t--) {
  22. scanf("%d", &n);
  23. memset(a, , sizeof a);
  24. memset(book , , sizeof book);
  25. for (int i = ; i <= n; i++) {
  26. for (int j = ; j <= ; j++) {
  27. scanf(" %c", &c);
  28. if (isdigit(c)) a[i] = a[i] * + c - '';
  29. else a[i] = a[i] * + + c - 'A';
  30. }
  31. book[a[i]] = ;
  32. }
  33. int flag = ;
  34. for (ans = ; ans <= ; ans++) {
  35. for (int s = ; s < ( << ); s++)
  36. if (cnt[s] == ans) {
  37. for (int i = ; i <= n; i++)
  38. if (book[s ^ a[i]]) {
  39. flag = ; break;
  40. }
  41. if (flag) break;
  42. }
  43. if (flag) break;
  44. }
  45. printf("%d\n", ans);
  46. }
  47.  
  48. return ;
  49. }

T4 [JZOJ3232] 排列

题目描述

  一个关于n个元素的排列是指一个从{1, 2, …, n}到{1, 2, …, n}的一一映射的函数。这个排列p的秩是指最小的k,使得对于所有的i = 1, 2, …, n,都有p(p(…p(i)…)) = i(其中,p一共出现了k次)。

  例如,对于一个三个元素的排列p(1) = 3, p(2) = 2, p(3) = 1,它的秩是2,因为p(p(1)) = 1, p(p(2)) = 2, p(p(3)) = 3。

  给定一个n,我们希望从n!个排列中,找出一个拥有最大秩的排列。例如,对于n=5,它能达到最大秩为6,这个排列是p(1) = 4, p(2) = 5, p(3) = 2, p(4) = 1, p(5) = 3。

  当我们有多个排列能得到这个最大的秩的时候,我们希望你求出字典序最小的那个排列。对于n个元素的排列,排列p的字典序比排列r小的意思是:存在一个整数i,使得对于所有j < i,都有p(j) = r(j),同时p(i) < r(i)。对于5来说,秩最大而且字典序最小的排列为:p(1) = 2, p(2) = 1, p(3) = 4, p(4) = 5, p(5) = 3。

数据范围

  对于 $40\%$ 的数据,$1 \leq N \leq 100$

  对于 $100\%$ 的数据,$1 \leq N \leq 10^4$

分析

  这题很像 2019 - 08 - 09 - T3

  这里是要求将 $n$ 分为若干数之和,使得这些数的最小公倍数最大

  然后就是做质数幂之积最大的多重背包了

  但这里的 $f$ 会很大,远超 $long \; long$ 的范围,所以可以将 $f$ 中的元素用自然对数表示

  最后显然就是把小的循环节放在前面,并且每个循环节中把第一个数放到节末输出

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. #define ll long long
  10. #define inf 0x3f3f3f3f
  11. #define N 10005
  12.  
  13. int T, n, m, last;
  14. int vis[N], p[N], t[N];
  15. pair<int, int> pre[][N];
  16. double f[][N], Log[N];
  17.  
  18. int main() {
  19. scanf("%d", &T);
  20. for (int i = ; i <= N; i++) {
  21. if (!vis[i]) p[++p[]] = i;
  22. for (int j = ; j <= p[]; j++) {
  23. if (i * p[j] > N) break;
  24. vis[i * p[j]] = ;
  25. }
  26. }
  27. for (int i = ; i <= N; i++) Log[i] = log(i);
  28. while (T--) {
  29. scanf("%d", &n);
  30. if (n == ) {printf("1\n"); continue;}
  31. for (int i = ; i <= n; i++) f[][i] = ;
  32. for (int i = ; i <= p[] && p[i] <= n; m = i, i++)
  33. for (int j = n; j >= p[i]; j--) {
  34. f[i & ][j] = f[(i & ) ^ ][j];
  35. pre[i][j] = pre[i - ][j];
  36. for (int k = p[i]; k <= j; k *= p[i])
  37. if (f[i & ][j] < f[(i & ) ^ ][j - k] + Log[k]) {
  38. f[i & ][j] = f[(i & ) ^ ][j - k] + Log[k];
  39. pre[i][j] = make_pair(i - , j - k);
  40. }
  41. }
  42. t[] = last = ;
  43. while (m && n) {
  44. int x = pre[m][n].first;
  45. int y = pre[m][n].second;
  46. t[++t[]] = n - y;
  47. m = x; n = y;
  48. }
  49. while (n--) t[++t[]] = ;
  50. sort(t + , t + t[] + );
  51. for (int i = ; i <= t[]; i++) {
  52. for (int j = ; j <= t[i]; j++)
  53. printf("%d ", last + j);
  54. printf("%d ", last + );
  55. last += t[i];
  56. }
  57. printf("\n");
  58. }
  59.  
  60. return ;
  61. }

2019-08-22 纪中NOIP模拟A&B组的更多相关文章

  1. 2019-08-21 纪中NOIP模拟A组

    T1 [JZOJ6315] 数字 题目描述

  2. 2019-08-15 纪中NOIP模拟B组

    T1 [JZOJ3455] 库特的向量 题目描述 从前在一个美好的校园里,有一只(棵)可爱的弯枝理树.她内敛而羞涩,一副弱气的样子让人一看就想好好疼爱她.仅仅在她身边,就有许多女孩子想和她BH,比如铃 ...

  3. 2019-08-01 纪中NOIP模拟B组

    T1 [JZOJ2642] 游戏 题目描述 Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有一个正整数.当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并 ...

  4. 2019-08-25 纪中NOIP模拟A组

    T1 [JZOJ6314] Balancing Inversions 题目描述 Bessie 和 Elsie 在一个长为 2N 的布尔数组 A 上玩游戏. Bessie 的分数为 A 的前一半的逆序对 ...

  5. 2019-08-23 纪中NOIP模拟A组

    T1 [JZOJ2908] 矩阵乘法 题目描述 给你一个 N*N 的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第 K 小数. 数据范围 对于 $20\%$ 的数据,$N \leq 100$,$Q ...

  6. 2019-08-20 纪中NOIP模拟B组

    T1 [JZOJ3490] 旅游(travel) 题目描述 ztxz16如愿成为码农之后,整天的生活除了写程序还是写程序,十分苦逼.终于有一天,他意识到自己的生活太过平淡,于是决定外出旅游丰富阅历. ...

  7. 2019-08-20 纪中NOIP模拟A组

    T1 [JZOJ6310] Global warming 题目描述 给定整数 n 和 x,以及一个大小为 n 的序列 a. 你可以选择一个区间 [l,r],然后令 a[i]+=d(l<=i< ...

  8. 2019-08-18 纪中NOIP模拟A组

    T1 [JZOJ6309] 完全背包 题目描述

  9. 2019-08-09 纪中NOIP模拟B组

    T1 [JZOJ1035] 粉刷匠 题目描述 windy有N条木板需要被粉刷. 每条木板被分为M个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一 ...

随机推荐

  1. [MacOS]Sublime text3 安装(一)

    官网地址 https://www.sublimetext.com/ 直接下载地址(MacOS) https://download.sublimetext.com/Sublime%20Text%20Bu ...

  2. 珠峰-webpack

    ##### webpack的优势.可以做哪里事情. ##### npx的运行原理  https://zhuanlan.zhihu.com/p/27840803 #### webpack的插件 html ...

  3. Vue.js 计算属性computed和methods的区别

    在vue.js中,有methods和computed两种方式来动态当作方法来用的 如下: 两种方式在这种情况下的结果是一样的 写法上的区别是computed计算属性的方式在用属性时不用加(),而met ...

  4. toj 3086 Passage (不错)

    Passage 时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte总提交: 40 测试通过: 20 描述 Bill is a millionaire. But ...

  5. java设计模式学习笔记--开闭原则

    基本介绍 1.开闭(ocp)原则时编程中最基础.最重要的设计原则 2.一个软件实体如类.木块和函数应该对扩展开放,对修改关闭.用抽象构建框架,用实现扩展细节.即对提供方开放,对使用方关闭. 3.当软件 ...

  6. SSM项目下Druid连接池的配置及数据源监控的使用

    一,连接池的配置 在pom.xml中添加,druid的maven信息 <dependency> <groupId>com.alibaba</groupId> < ...

  7. POJ - 1426-Find The Multiple-专为小白解惑-同余加搜索树

    题意:给出一个整数n,(1 <= n <= 200).求出任意一个它的倍数m,要求m必须只由十进制的'0'或'1'组成,m不超过100位. 解题思路:首先大家应该会想到暴力枚举每一个m,但 ...

  8. FIB表中 Next Hop 的几种状态码(drop/receive/attached/no route)的含义

    以一个例子来说明,假设有如下两个路由器R1,R2,且均配置了到达彼此环回地址的静态路由. (1.1.1.1/24)R1(Gig0/0)(.1)——12.0.0.0/24——(.2)(Gig0/0)R2 ...

  9. postman设置变量

    参数化 变量引用格式:{{username}}   , 区别jmeter的  {username} 一.设置与引用环境变量 背景:在不同的环境下跑相同的测试,生产环境或测试环境 二.设置与引用全局变量 ...

  10. 简述react、redux、react-redux、redux-saga、dva之间的关系

    [react] 定位:React 是一个用于构建用户界面的JavaScript库. 特点:它采用声明范式来描述应用,建立虚拟dom,支持JSX语法,通过react构建组件,能够很好的去复用代码: 缺点 ...