数组分割(2023省蓝桥杯)n种讨论 JAVA

目录

  • 1、题目描述:
  • 2、前言:
  • 3、动态规划(bug):
  • 3、递归 + 剪枝(超时):
  • 4、数学(正解):

1、题目描述:

小蓝有一个长度为 N 的数组 A = [A0, A1,…, AN−1]。现在小蓝想要从 A 对应的数组下标所构成的集合 I = {0, 1,
2, . . . , N − 1} 中找出一个子集 R1,那么 R1在 I 中的补集为 R2。记 S1=∑r∈R1Ar,S2
=∑r∈R2Ar,我们要求 S1 和 S2 均为偶数,请问在这种情况下共有多少种不同的 R1。当 R1 或 R2 为空集时我们将 S1 或 S2 视为 0。 输入格式 第一行一个整数 T,表示有 T 组数据。 接下来输入 T 组数据,每组数据包含两行:第一行一个整数 N,表示数组
A 的长度;第二行输入 N 个整数从左至右依次为 A0, A1, . . . , AN−1,相邻元素之间用空格分隔。 输出格式
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你需要将答案对1000000007 进行取模后输出。

样例输入:

2
2
6 6
2
1 6

样例输出:

4
0

[提示]
对于第一组数据,答案为 4。(注意:大括号内的数字表示元素在数组中的下标。)
R1 = {0}, R2 = {1};此时 S1 = A0 = 6 为偶数, S2 = A1 = 6 为偶数。
R1 = {1}, R2 = {0};此时 S1 = A1 = 6 为偶数, S2 = A0 = 6 为偶数。
R1 = {0, 1}, R2 = {};此时 S1 = A0 + A1 = 12 为偶数, S2 = 0 为偶数。
R1 = {}, R2 = {0, 1};此时 S1 = 0 为偶数, S2 = A0 + A1 = 12 为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为 0。

对于 20% 的评测用例,1 ≤ N ≤ 10。
对于 40% 的评测用例,1 ≤ N ≤ 10^2。
对于 100% 的评测用例,1 ≤ T ≤ 10, 1 ≤ N ≤ 103 , 0 ≤ Ai ≤ 10^9。


2、前言:

这题考完蓝桥杯之后,自闭地看着答案整理过一遍,当时一度认为只能用数学方法做,而且当时也意识到自己见识太少,所以这俩月一直在埋头苦刷暂避锋芒。这不,这两天感觉自己又行了再来回顾本题,看看能否用新的算法做,以下是思考结果:


3、动态规划(bug):

最开始想到的就是用动态规划解决本题,虽然动态规划学的不熟,但是有思路就能写出来,本题还是不建议用动态规划解因为题目给的数据太大,非常容易爆数组。

1、本题与01背包有些许相似所以用01背包思想试解

2、dp[ i ][ j ] = n即:考虑前i个元素挑选出的元素和为j的方案数为n

3、初始化dp[i][0] = 1,考虑前i个元素,和为0的方案数为什么都不选1种

4、对于元素i无非选与不选两种,dp[i][j]=dp[i - 1][j] + dp[i - 1][j - nums[j]],前提是j >= nums[j]

5、最后取所有dp[len][j]且j是偶数的元素即可

错误代码1:

import java.util.*;public class Text2{//继承父类Jframe,获取父类方法public static int mod = 1000000007;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();for(int i = 0; i < n; i ++) {int len = sc.nextInt();int nums[] = new int[len + 1];for(int j = 1; j <= len; j ++) nums[j] = sc.nextInt();System.out.println(dfs(nums, len));}}public static int dfs(int nums[], int len) {int num = 0;for(int j = 1; j <= len; j ++) num = num + nums[j];if(num % 2 != 0) return 0;int dp[][]  = new int[len + 1][num + 1];for(int i = 0; i <= len; i ++) dp[i][0] = 1;int cnt = 1;for(int i = 1; i <= len; i ++) {for(int j = 1; j <= num; j ++) {dp[i][j] = dp[i - 1][j]; if(j >= nums[i])dp[i][j] = dp[i][j] + dp[i - 1][j - nums[i]];if(i == len && j % 2 == 0) {cnt = cnt + dp[i][j];System.out.println(i + " " + j + " " + dp[i][j]);}}}return cnt;}}

想着用一维数组优化
错误代码1优化版:

import java.util.*;public class Text1{//继承父类Jframe,获取父类方法public static int mod = 1000000007;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();for(int i = 0; i < n; i ++) {int len = sc.nextInt();int nums[] = new int[len + 1];for(int j = 1; j <= len; j ++) nums[j] = sc.nextInt();System.out.println(dfs(nums, len));}}public static int dfs(int nums[], int len) {int num = 0;for(int j = 1; j <= len; j ++) num = num + nums[j];if(num % 2 != 0) return 0;int dp[]  = new int[num + 1];dp[0] = 1;//考虑前0件元素得到0的方法有1个int cnt = 1;for(int j = 1; j <= len; j ++)//考虑前len个元素for(int z = num; z >= nums[j]; z --){dp[z] = dp[z] + dp[z - nums[j]];if(j == len && z % 2 == 0 && (num - z) % 2 == 0) cnt = (cnt + dp[z]) % mod;}return cnt;}}

解题思路:

为什么看着思路没问题题,但却还是错误代码呢,因为题目的数据含有0!!!

以正常没有0的[2, 4]为例子:

在这里插入图片描述

动态规划需要通过数组迭代,对于元素i无非就是选与不选但当元素nums[i] = 0的时候,选了与没选是不确定的其无法从初始dp[0][0]迭代过来以有0的[0, 2]为例子:

在这里插入图片描述
元素无法从dp[0][0]迭代出去,形成了不通路。

值得一提的是优化代码错误更多

以[2, 2, 4]为例,未优化与优化代码数组迭代过程如下:

在这里插入图片描述

由于一维数组从后往前遍历dp[3][2]虽然符合条件但是无法从dp[2][2]迭代下来(2 < 4)

如果数据范围>0的话动态规划还是能在不爆数组的情况下都对的以下是产生随机数据的代码以及测试结果

代码:

import java.awt.print.Printable;
import java.util.*;public class Text4{public static int mod = 1000000007;public static void main(String[] args) { for(int i = 0; i < 1000; i ++) {Scanner sc = new Scanner(System.in);int len = new Random().nextInt(1000) + 1;
//    	    	int len = sc.nextInt();int nums[] = new int[len + 1];for(int j = 1; j <= len; j ++) 
//    		    	nums[j] = sc.nextInt();nums[j] = new Random().nextInt(1000) + 1;boolean flag =  (dfs(nums, len) == ddffs(nums, len));System.out.println(flag);if(!flag) {print(nums, dfs(nums, len), ddffs(nums, len));return;}}}public static int dfs(int nums[], int len) {int num = 0;for(int j = 1; j <= len; j ++) num = num + nums[j];if(num % 2 != 0) return 0;int dp[][]  = new int[len + 1][num + 1];for(int i = 0; i <= len; i ++) dp[i][0] = 1;int cnt = 1;for(int i = 1; i <= len; i ++)for(int j = 1; j <= num; j ++) {dp[i][j] = dp[i - 1][j]; if(j >= nums[i])dp[i][j] = (dp[i][j] + dp[i - 1][j - nums[i]]) % mod;if(i == len && j % 2 == 0) cnt = (cnt + dp[i][j]) % mod;}return cnt;}public static int ddffs(int a[], int m) {int L = 0, J = 0; for(int i = 1; i <= m; i ++) if(a[i] % 2 == 0) L ++;else J ++;if(J % 2 != 0) return 0;else {if(J == 0) J = 1;return (int)(Math.pow(2, L) * Math.pow(2, J - 1) % mod);}}public static void print(int a[], int b, int c) {System.out.println(a.length - 1 + " " + b + " " + c);for(int i = 1; i < a.length; i ++) System.out.print(a[i] + " ");}
}

在这里插入图片描述

好动态规划到此宣布破产


3、递归 + 剪枝(超时):

考试的时候就是用递归做的,但是太傻比了,退出条件不对,我早就应该知道递归的每条路径就是一种遍历情况,当时以及昨天我却在分枝上找答案太傻逼了,答案应该在递归末尾节点找。

在这里插入图片描述
太傻比了之前用递归一直是在分支上找答答案,跟本没啥意义,再加上有0的出现我一直以为本题不能用常规递归做,用什么分治思想之类的。。。刚在才醒悟过来,把递归图画了以下才醒悟,根本没必要那么复杂直接在递归末尾节点判断就行了

每个元素都是选与不选两种情况,从首节点到任意末尾节点都是一条路径,本题来说是选元素的其中一种选法,只需要判断满不满足题意就行了,太傻比了希望以后不要再犯这种错误了!

代码:

import java.util.Scanner;public class Text6 {//继承父类Jframe,获取父类方法public static int mod = 1000000007;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();for(int j = 0; j < m; j ++) {long sum = 0;int n = sc.nextInt();int nums[] = new int[n];for(int i = 0; i < n; i ++) {nums[i] = sc.nextInt();sum = sum + nums[i];}if(sum % 2 == 0)System.out.println(dfs(nums, n, 0, 0));elseSystem.out.println(0);}}public static int dfs(int nums[], int len, int i, long sum) {if(i == len) {if(sum % 2 == 0) return 1;return 0;}int choosethis = dfs(nums, len, i + 1, sum + nums[i]) % mod;int notchoose = dfs(nums, len, i + 1, sum) % mod;return (choosethis + notchoose) % mod;}}

在这里插入图片描述
超时是意料之内,剪一下枝即可

优化代码:

用二维数组可能会爆掉,用大杀器其map应该就能拿下本题:

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class Text7 { public static Map<String, Integer> map;public static int mod = 1000000007;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();for(int j = 0; j < m; j ++) {map = new HashMap<String, Integer>();long sum = 0;int n = sc.nextInt();int nums[] = new int[n];for(int i = 0; i < n; i ++) {nums[i] = sc.nextInt();sum = sum + nums[i];}if(sum % 2 == 0)System.out.println(dfs(nums, n, 0, 0));elseSystem.out.println(0);}}public static int dfs(int nums[], int len, int i, long sum) {if(map.containsKey(i + " " + sum)) return map.get(i + " " + sum);if(i == len) {if(sum % 2 == 0) return 1;return 0;}int choosethis = dfs(nums, len, i + 1, sum + nums[i]) % mod;int notchoose = dfs(nums, len, i + 1, sum) % mod;map.put(i + " " + sum, (choosethis + notchoose) % mod);return (choosethis + notchoose) % mod;}}

看一下成果!

在这里插入图片描述
我真是热烈的🐎测了好几遍一个样,要么测试的地方不行,要么map查表和剪纸的部分正负得零,反正麻了

算了不重要了,最后再说一下为什么递归不会被0影响,这从递归图可以看出来

在这里插入图片描述
递归每条路径都是一个选择情况,即使两个0也可以清楚看出所有情况。


4、数学(正解):

详细解析在这里:
2023年第十四届蓝桥杯JavaB组省赛真题及解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/52112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【⑭MySQL | 数据类型(二)】字符串 | 二进制类型

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL字符串 | 二进制类型类型的分享✨ 目录 前言5 字符串类型6 二进制类型总结 5 字符串类型 字符串类型用来存储字符串数据&#xff0c;还可以存储图片和声音的二进制数据。字符串可以区分或者不区分大小写的串比…

PDF如何转ppt?PDF转ppt的方法

PDF是一种广泛应用于文档传输和存储的格式&#xff0c;然而&#xff0c;在某些情况下&#xff0c;我们可能需要将PDF文件转换为PPT&#xff0c;以便更加灵活地编辑和展示内容。那么&#xff0c;PDF如何转ppt呢?在本文中&#xff0c;我们将介绍几种常用的方法和工具&#xff0c…

总结:Git 撤销操作

1、还未添加到暂存区&#xff1a;git checkout -- filename 执行命令后&#xff0c;会回退到未修改之前的状态 2、已经添加到暂存区&#xff1a;git reset HEAD filename 执行命令后&#xff0c;会回退到工作区之前的状态 3、已经 commit&#xff0c;但是还未 push git reset…

VLOOKUP

VLOOKUP简单应用 VLOOKUP(A1,B:B,1,FALSE) 是查询A1这子格子的数据在B这一列里面有没有找到相同数据的值,如果有的话就放在当前格子里面去 如果没有的话就是#NA VLOOKUP(A1,F:G,2,FALSE) 是查询A1这子格子的数据在F列查相同的数据,然后再取G列这一行后面的这个格子的数据放到…

【算法刷题之哈希表(2)】

目录 1.leetcode-454. 四数相加 II2.leetcode-383. 赎金信&#xff08;1&#xff09;暴力解法&#xff08;2&#xff09;哈希法 3.leetcode-205. 同构字符串&#xff08;1&#xff09;哈希法&#xff08;2&#xff09;直接对比查找 4.leetcode-128. 最长连续序列5.总结 1.leetc…

mysql-sql性能分析工具

一、sql执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令&#xff0c;可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次&#xff1a; -- session 是查看当前会话 ; -- global 是查询全…

【硕士论文完美复现】【价格型需求响应】基于需求侧响应的配电网供电能力综合评估(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

七大排序算法详解

1.概念 1.排序的稳定性 常见的稳定的排序有三种&#xff1a;直接插入排序&#xff0c;冒泡排序&#xff0c;归并排序 对于一组数据元素排列&#xff0c;使用某种排序算法对它进行排序&#xff0c;若相同数据之间的前后位置排序后和未排序之前是相同的&#xff0c;我们就成这种…

vue3 vite使用 monaco-editor 报错

报错&#xff1a;Unexpected usage at EditorSimpleWorker.loadForeignModule 修改配置&#xff1a; "monaco-editor-webpack-plugin": "^4.2.0",删除不用 版本&#xff1a; "monaco-editor": "^0.28.1", 修改如下&#xff1a; opti…

stm32 无刷电机 V/F控制(无刷电机变频控制)以及与foc(矢量控制)的区别

无刷电机有三种控制方式&#xff0c;方波控制&#xff0c;foc控制以及变频控制&#xff0c;前两章我们讲解了方波和foc的控制方法&#xff0c;今天我们一起来讲一讲什么是无刷电机的变频控制&#xff08;VF&#xff09;以及变频控制的优势是什么。 实验用的硬件还是KY_Motor的无…

IDEA远程开发

IDEA远程开发 前期准备 IDEA的远程开发是在本地去操昨远程服务器上的代码&#xff0c;所以我们先需要准备一台服务器,在此我使用vmware虚拟出ubuntu-20.04.6的Server版本,以便后面演示。 Ubuntu的Java环境配置 JDK8 sudo apt install openjdk-8-jdkmaven sudo apt instal…

三星申请新商标:未来将应用于智能戒指,作为XR头显延伸设备

三星最近向英国知识产权局提交了名为“Samsung Curio”的新商标&#xff0c;这预示着三星正积极扩展可穿戴设备生态。该商标被分类为“Class 9”&#xff0c;这表明它有可能被用于未来的智能戒指。 据报道&#xff0c;三星计划将智能戒指作为XR头显设备的延伸&#xff0c;与苹果…

面试题-React(六):React组件和生命周期

一、React组件 React组件简介&#xff1a; React组件是构建用户界面的基本单元。它们将界面拆分成独立、可重用的部分&#xff0c;使得代码更加模块化、可维护性更高。React组件可以是函数组件或类组件&#xff0c;它们接收输入的数据&#xff08;称为props&#xff09;并返回…

基于PaddlePaddle实现的声纹识别系统

前言 本项目使用了EcapaTdnn、ResNetSE、ERes2Net、CAM等多种先进的声纹识别模型&#xff0c;不排除以后会支持更多模型&#xff0c;同时本项目也支持了MelSpectrogram、Spectrogram、MFCC、Fbank等多种数据预处理方法&#xff0c;使用了ArcFace Loss&#xff0c;ArcFace loss…

ETLCloud轻量级数据中台解决方案

引言 随着信息时代的到来&#xff0c;数据已经成为企业的重要资源&#xff0c;如何高效地管理、分析和应用数据变得尤为关键。然而&#xff0c;许多企业在构建数据中台时面临着高昂的成本、复杂的架构和漫长的实施周期等问题。为了解决这些挑战&#xff0c;我们推出了ETLCloud…

java八股文面试[java基础]——CGLIB动态代理与JDK动态代理

CGLIB CGLIB简介&#xff1a; 什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c;同样使用CGLIB来代理单端&#xff…

利用LLM模型微调的短课程;钉钉宣布开放智能化底座能力

&#x1f989; AI新闻 &#x1f680; 钉钉宣布开放智能化底座能力AI PaaS&#xff0c;推动企业数智化转型发展 摘要&#xff1a;钉钉在生态大会上宣布开放智能化底座能力AI PaaS&#xff0c;与生态伙伴探寻企业服务的新发展道路。AI PaaS结合5G、云计算和人工智能技术的普及和…

文心一言 VS 讯飞星火 VS chatgpt (81)-- 算法导论7.4 6题

六、如果用go语言&#xff0c;考虑对 PARTITION 过程做这样的修改:从数组 A 中随机选出三个元素&#xff0c;并用这三个元素的中位数(即这三个元素按大小排在中间的值)对数组进行划分。求以a 的函数形式表示的、最坏划分比例为 a:(1-a)的近似概率&#xff0c;其中 0<a<1。…

卡尔曼滤波学习笔记

Kalman Filter Ⅰ、直观理解1、描述2、例子 Ⅱ、适用范围1、线性系统2、噪声服从高斯分布 Ⅲ、相关公式1、原始公式2、预测公式3、更新公式4、初值赋予5、总结 Ⅳ、应用例子Ⅴ、代码实现Ⅵ、公式理解1、协方差矩阵的理解1.1 协方差1.2 协方差矩阵1.3、相关数学公式 2、状态方程…

Android12之ABuffer数据处理(三十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…