diff --git "a/ACWing/src/DFS/\346\240\221\347\232\204\351\207\215\345\277\203.java" "b/ACWing/src/DFS/\346\240\221\347\232\204\351\207\215\345\277\203.java" index 8dcda7fed10534acb82d3164af52e740e7fbe6ca..689a8c89455f43e4024f8357af68d516e0158d49 100644 --- "a/ACWing/src/DFS/\346\240\221\347\232\204\351\207\215\345\277\203.java" +++ "b/ACWing/src/DFS/\346\240\221\347\232\204\351\207\215\345\277\203.java" @@ -5,8 +5,42 @@ import java.util.Scanner; public class 树的重心 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); - + n = sc.nextInt(); + int a, b; + for (int i = 0; i < n - 1; i++) { + a = sc.nextInt(); + b = sc.nextInt(); + add(a, b); + add(b, a); + } + dfs(1); + System.out.println(ans); } - static int n, m; + private static int dfs(int u) { + vis[u] = 1; + int size = 0, sum = 0; + for (int i = he[u]; i != 0; i = ne[i]) { + int j = e[i]; + if (vis[j] == 1) continue; + int s = dfs(j); + size = Math.max(size, s); + sum += s;//加上孩子节点的个数 + } + size = Math.max(size, n - sum - 1); + ans = Math.min(ans, size); + return sum + 1; + } + + static int n, cnt, ans=Integer.MAX_VALUE; + static int[] he = new int[100100]; + static int[] ne = new int[200100]; + static int[] e = new int[200100]; + static int[] vis = new int[100100]; + + static void add(int a, int b) { + e[cnt] = b; + ne[cnt] = he[a]; + he[a] = cnt++; + } } diff --git "a/ACWing/src/\346\225\260\345\255\246/\346\254\247\346\213\211\345\207\275\346\225\260.java" "b/ACWing/src/\346\225\260\345\255\246/\346\254\247\346\213\211\345\207\275\346\225\260.java" new file mode 100644 index 0000000000000000000000000000000000000000..39593df1324dd2a2560f14216b20369341f128b9 --- /dev/null +++ "b/ACWing/src/\346\225\260\345\255\246/\346\254\247\346\213\211\345\207\275\346\225\260.java" @@ -0,0 +1,21 @@ +package 数学; +//https://blog.csdn.net/weixin_43237242/article/details/97388834 +public class 欧拉函数 { + public static void main(String[] args) { + System.out.println(euler(6)); + } + + static long euler(long n) { + long ans = n; + for (int i = 2; i * i <= n; i++) { + if (n % i == 0) { + ans = ans / i * (i - 1); + while (n % i == 0) { + n/=i; + } + } + } + if (n>1)ans=ans/n*(n-1); + return ans; + } +} diff --git "a/ACWing/src/\346\225\260\345\255\246/\347\272\277\346\200\247\347\255\233.java" "b/ACWing/src/\346\225\260\345\255\246/\347\272\277\346\200\247\347\255\233.java" new file mode 100644 index 0000000000000000000000000000000000000000..7636d0fa907a6d8c8cfff3e017724865464926ba --- /dev/null +++ "b/ACWing/src/\346\225\260\345\255\246/\347\272\277\346\200\247\347\255\233.java" @@ -0,0 +1,45 @@ +package 数学; + +//线性筛质数 +public class 线性筛 { + public static void main(String[] args) { + oldN(1234567); + } + + static int cnt = 0; + static int[] prime = new int[100]; + static boolean[] vis = new boolean[10000]; + + //让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。 + //太过牛逼只能背下来 + static void ol(int n) { + for (int i = 2; i <= n; i++) { + if (!vis[i]) prime[cnt++] = i; + for (int j = 0; prime[j] <= n / i; j++) { + vis[prime[j] * i] = true; + if (i % prime[j] == 0) break; + } + } + } + + static void oldN(int N) { + int n = N; + int r = 0; + while ((n / Math.log(n)) < N) { + r++; + n += 599; + } + System.out.println(r); + int cnt = 0; + prime = new int[n + 1]; + vis = new boolean[n + 1]; + for (int i = 2; i <= n; i++) { + if (!vis[i]) prime[cnt++] = i; + for (int j = 0; prime[j] <= n / i; j++) { + vis[prime[j] * i] = true; + if (i % prime[j] == 0) break; + } + } + System.out.println(prime[N - 1]); + } +} diff --git "a/ACWing/src/\346\240\221\345\275\242dp/\346\234\211\344\276\235\350\265\226\347\232\204\350\203\214\345\214\205\351\227\256\351\242\230.java" "b/ACWing/src/\346\240\221\345\275\242dp/\346\234\211\344\276\235\350\265\226\347\232\204\350\203\214\345\214\205\351\227\256\351\242\230.java" index 11596df5c7091703cd4c888d1863f4ff4ce7f796..9f6d5e67616d6d4c8dcb575e044d74d154db37b7 100644 --- "a/ACWing/src/\346\240\221\345\275\242dp/\346\234\211\344\276\235\350\265\226\347\232\204\350\203\214\345\214\205\351\227\256\351\242\230.java" +++ "b/ACWing/src/\346\240\221\345\275\242dp/\346\234\211\344\276\235\350\265\226\347\232\204\350\203\214\345\214\205\351\227\256\351\242\230.java" @@ -11,23 +11,89 @@ import java.util.Scanner; * 状态定义:集合f[u,j]:所有从以u为根的子树中选,且总体积不超过j的选法 * 属性:max最大价值 * 集合划分:子树1,子树3,子树3 - * 再根据体积划分子树:体积是0-m + * 再根据体积划分子树:体积是0-m 有m+1总可能 + * 用一个数字表示一类方案 * 把每一颗子树看做物品组,分组背包问题 * 链式前向星建图 + * 有 N 个物品和一个容量是 V + * 的背包。 + * 物品之间具有依赖关系,且依赖关系组成一棵树的形状。如果选择一个物品,则必须选择它的父节点。 + * 如下图所示: + * 如果选择物品5,则必须选择物品1和2。这是因为2是5的父节点,1是2的父节点。 + * 每件物品的编号是 i + * ,体积是 vi,价值是 wi,依赖的父节点编号是 pi。物品的下标范围是 1…N + * 求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。 + * 输出最大价值。 + * 输入格式 + * 第一行有两个整数 N,V + * ,用空格隔开,分别表示物品个数和背包容量。 + * 接下来有 N + * 行数据,每行数据表示一个物品。 + * 第 i 行有三个整数 vi,wi,pi,用空格隔开,分别表示物品的体积、价值和依赖的物品编号。 + * 如果 pi=−1 + * ,表示根节点。 数据保证所有物品构成一棵树。 + * 输出格式 + * 输出一个整数,表示最大价值。 + * 数据范围 + * 1≤N,V≤100 + * 1≤vi,wi≤100 + * 父节点编号范围: + * 内部结点:1≤pi≤N + * 根节点 pi=−1 + * 输入样例 + * 5 7 + * 2 3 -1 + * 2 2 1 + * 3 5 1 + * 4 7 2 + * 3 6 2 + * 输出样例: + * 11 */ public class 有依赖的背包问题 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); - v = sc.nextInt(); + m = sc.nextInt(); + int p, root = 0; + for (int i = 1; i <= n; i++) { + v[i] = sc.nextInt(); + w[i] = sc.nextInt(); + p = sc.nextInt(); + if (p == -1) root = i; + else add(p, i); + } + dfs(root); + System.out.println(f[root][m]); + } + static void dfs(int u) { + for (int i = head[u]; i != 0; i = ne[i]) { + int son = e[i]; + dfs(e[i]); + for (int j = m - v[u]; j >= 0; j--) {//枚举体积 + for (int k = 0; k <= j; k++) {//枚举决策,分为以0~m的一些决策 + f[u][j] = Math.max(f[u][j], f[u][j - k] + f[son][k]); + //以u为根节点,在剩余体积为0~m-v[u]的情况下,选子树 + } + } + } + for (int i = m; i >= v[u]; i--) { + f[u][i] = f[u][i - v[u]] + w[u]; + }//遍历完根节点的所有子树后 + //能选的一定要选上01背包问题 + for (int i = 0; i < v[u]; i++) { + f[u][i] = 0; + }//如果不能选赋值为0 } + static int[] v = new int[110], w = new int[110]; + static int[][] f = new int[110][110]; static int N = 110; static int[] head = new int[N], e = new int[N], ne = new int[N]; - static int n, v, cnt = 1; + static int n, m, cnt = 1; static void add(int a, int b) { e[cnt] = b; diff --git "a/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\347\233\264\345\276\204.java" "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\347\233\264\345\276\204.java" new file mode 100644 index 0000000000000000000000000000000000000000..18d52f60fa7bbe5fdc99d3ff885ba28d7cf2b5b9 --- /dev/null +++ "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\347\233\264\345\276\204.java" @@ -0,0 +1,7 @@ +package 树形dp; + +public class 树的直径 { + public static void main(String[] args) { + + } +} diff --git "a/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\351\207\215\345\277\203.java" "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\351\207\215\345\277\203.java" new file mode 100644 index 0000000000000000000000000000000000000000..5f6ad93337f161e3613967abf8e45c379c38823c --- /dev/null +++ "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\347\232\204\351\207\215\345\277\203.java" @@ -0,0 +1,58 @@ +package 树形dp; + +import java.util.Scanner; + +/** + * https://blog.csdn.net/qq_30277239/article/details/100988651 + * 树的重心是指树上一点,去掉后最大子树可以取得最小值的点。 + * 去掉重心后,最大子树大小不超过n/2 + * 下面简单描述下本题的解题过程。要想找到树的重心,需要知道去掉某节点后剩下连通块中节点的数量,对于某个节点u,以u为根节点的子树的节点总数为x,则其父节点(若存在)所在连通块节点的数目为n-x。要求以某节点为根节点子树的节点的个数,只需要递归的求以其孩子节点为根节点子树的总和即可。设int dfs(int u)这个函数能够实现该功能,则想要统计u所有子树节点之和,只需要int sum = 0;u的孩子节点比如有a,b,sum + dfs(a)+dfs(b) + 1即是u所在子树节点的总和了,同时,还可以求各个连通块节点的最大值,找到树的重心。 + */ +public class 树的重心 { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + n = sc.nextInt(); + int a, b; + for (int i = 1; i < n; i++) { + a = sc.nextInt(); + b = sc.nextInt(); + + add(a, b); + add(b, a); + } + dfs(1); + // System.out.println(ans); + } + + private static int dfs(int u) { + vis[u] = true; + int size = 0, sum = 0; + // + for (int i = he[u]; i != 0; i = ne[i]) { + int j = e[i]; + if (vis[j]) continue;//不用遍历父节点 + int s = dfs(j); + size = Math.max(size, s); + sum += s; + } + size = Math.max(size, n - sum - 1); + ans = Math.min(ans, size); + System.out.println(ans); + return sum + 1;//sum不+1就会恒等于0 + } + + static int ans = Integer.MAX_VALUE; + + static boolean[] vis = new boolean[(int) (1e5 + 4)]; + static int[] he = new int[(int) (1e5 + 4)]; + static int[] ne = new int[(int) (2e5 + 4)]; + static int[] e = new int[(int) (2e5 + 4)]; + + static int cnt = 1, n; + + static void add(int a, int b) { + e[cnt] = b; + ne[cnt] = he[a]; + he[a] = cnt++; + } +} diff --git "a/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\351\207\215\345\277\203\346\211\276\350\212\202\347\202\271.java" "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\351\207\215\345\277\203\346\211\276\350\212\202\347\202\271.java" new file mode 100644 index 0000000000000000000000000000000000000000..8dc2e8aea46d8b8e22bc69a518440a9f3f5f1239 --- /dev/null +++ "b/ACWing/src/\346\240\221\345\275\242dp/\346\240\221\351\207\215\345\277\203\346\211\276\350\212\202\347\202\271.java" @@ -0,0 +1,66 @@ +package 树形dp; + +import java.util.Arrays; +import java.util.Scanner; + +/** + * https://blog.csdn.net/qq_43326267/article/details/89789239 + * 把每个节点看做根 + * 9 + * 1 2 + * 2 3 + * 2 4 + * 4 5 + * 1 6 + * 6 7 + * 7 8 + * 7 9 + */ +public class 树重心找节点 { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + n = sc.nextInt(); + for (int i = 1; i < n; i++) { + add(sc.nextInt(), sc.nextInt()); + } + dfs(1); + System.out.println(Arrays.toString(size)); + System.out.println(Arrays.toString(maxpart)); + + } + + private static void dfs(int u) { + vis[u] = true; + size[u] = 1; + for (int i = he[u]; i != 0; i = ne[i]) { + int j = e[i]; + if (vis[j]) continue; + dfs(j); + size[u] += size[j]; + maxpart[u] = Math.max(maxpart[u], size[j]); + + } + maxpart[u] = Math.max(maxpart[u], n - size[u]); + //算出以u为根,u的父节点所在联通分量的节点数目 + ans = Math.min(ans, maxpart[u]); + } + + static int ans = Integer.MAX_VALUE; + + static int[] size = new int[10010]; + static int[] maxpart = new int[10010]; + static int[] he = new int[10900]; + static boolean[] vis = new boolean[10010]; + static int[] ne = new int[10900 * 2]; + static int[] e = new int[10900 * 2]; + static int cnt = 1, n; + + static void add(int a, int b) { + e[cnt] = b; + ne[cnt] = he[a]; + he[a] = cnt++; + e[cnt] = a; + ne[cnt] = he[b]; + he[b] = cnt++; + } +} diff --git "a/ACWing/src/\346\240\221\345\275\242dp/\346\262\241\346\234\211\344\270\212\345\217\270\347\232\204\350\210\236\344\274\232.java" "b/ACWing/src/\346\240\221\345\275\242dp/\346\262\241\346\234\211\344\270\212\345\217\270\347\232\204\350\210\236\344\274\232.java" index 1a2c80817193eaeaa8995474e3e5ae718a2cfd14..160bfdf3aa428e4d58be0e9682615d169b0de23b 100644 --- "a/ACWing/src/\346\240\221\345\275\242dp/\346\262\241\346\234\211\344\270\212\345\217\270\347\232\204\350\210\236\344\274\232.java" +++ "b/ACWing/src/\346\240\221\345\275\242dp/\346\262\241\346\234\211\344\270\212\345\217\270\347\232\204\350\210\236\344\274\232.java" @@ -7,7 +7,7 @@ public class 没有上司的舞会 { Scanner sc = new Scanner(System.in); n = sc.nextInt(); for (int i = 1; i <= n; i++) { - happy[i] = sc.nextInt(); + f[i][1] = sc.nextInt(); } int a, b; for (int i = 0; i < n - 1; i++) { @@ -23,11 +23,11 @@ public class 没有上司的舞会 { } private static void dfs(int u) { - f[u][1] = happy[u];//选择了u就加上u的幸福指数 + // f[u][1] = happy[u];//选择了u就加上u的幸福指数 for (int i = he[u]; i != 0; i = ne[i]) { int j = e[i]; dfs(j); - f[u][1] += f[j][0];//不选子节点 + f[u][1] += f[j][0];//选当前节点,但不选子节点 f[u][0] += Math.max(f[j][0], f[j][1]); //不选当前节点,是选还是不选子节点 } diff --git "a/ACWing/src/\347\272\277\346\200\247dp/\350\203\214\345\214\205\346\250\241\345\236\213/\351\207\221\346\230\216\347\232\204\351\242\204\347\256\227\346\226\271\346\241\210.java" "b/ACWing/src/\347\272\277\346\200\247dp/\350\203\214\345\214\205\346\250\241\345\236\213/\351\207\221\346\230\216\347\232\204\351\242\204\347\256\227\346\226\271\346\241\210.java" index 22f2be9f0d51b5fa088d743d968210ad975d333d..e86eae357251db93321e4648d9d6fce54cb3ad71 100644 --- "a/ACWing/src/\347\272\277\346\200\247dp/\350\203\214\345\214\205\346\250\241\345\236\213/\351\207\221\346\230\216\347\232\204\351\242\204\347\256\227\346\226\271\346\241\210.java" +++ "b/ACWing/src/\347\272\277\346\200\247dp/\350\203\214\345\214\205\346\250\241\345\236\213/\351\207\221\346\230\216\347\232\204\351\242\204\347\256\227\346\226\271\346\241\210.java" @@ -50,7 +50,6 @@ import java.util.Scanner; * 可以算出价值和体积 * 状态划分:不选第i种组件,f[i-1,j] * 选第i种主件:f[i-1,j-v]+w 和第一个附件f[i-1,j-v]+w .... 或者不选第一个附件,选第二个附件... - * */ public class 金明的预算方案 { static class node { diff --git "a/\347\256\227\346\263\225\345\276\210\347\276\216/src/Math/\346\254\247\346\213\211\347\272\277\346\200\247\347\255\233\346\234\200\345\277\253\347\232\204.java" "b/\347\256\227\346\263\225\345\276\210\347\276\216/src/Math/\346\254\247\346\213\211\347\272\277\346\200\247\347\255\233\346\234\200\345\277\253\347\232\204.java" index f159a1b5fa4a05fad688c5a33345efd5ea6dc98d..7993aebf1725a024215fbeea5bcef64eb7157aaf 100644 --- "a/\347\256\227\346\263\225\345\276\210\347\276\216/src/Math/\346\254\247\346\213\211\347\272\277\346\200\247\347\255\233\346\234\200\345\277\253\347\232\204.java" +++ "b/\347\256\227\346\263\225\345\276\210\347\276\216/src/Math/\346\254\247\346\213\211\347\272\277\346\200\247\347\255\233\346\234\200\345\277\253\347\232\204.java" @@ -2,7 +2,7 @@ package Math; public class 欧拉线性筛最快的 { public static void main(String[] args) { - eluer(12345); + eluer(12345798); } static int[] prime;