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

news2024/9/22 13:41:24

目录

  • 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));
    	   else
    		   System.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));
    	   else
    		   System.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.coloradmin.cn/o/909024.html

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

相关文章

3分钟通过日志定位bug,这个技能测试人必须会!

♥ 前 言 软件开发中通过日志记录程序的运行情况是一个开发的好习惯&#xff0c;对于错误排查和系统运维都有很大帮助。 Python 标准库自带了强大的 logging 日志模块&#xff0c;在各种 python 模块中得到广泛应用。 一、简单使用 1. 入门小案例 import logging loggin…

sync修饰符(重要)

作用&#xff1a;可以实现 子组件 与 父组件 数据的双向绑定 简化代码 特点&#xff1a;prop属性名&#xff0c;可以自定义&#xff0c;非固定为value 场景&#xff1a;封装弹框类的基础组件&#xff0c;visible属性 true显示 false隐藏 本质&#xff1a;就是 :属性名 和 updat…

SpringBoot 配置优先级

一般而言&#xff0c;SpringBoot支持配置文件进行配置&#xff0c;即在resources下的application.properties或application.yml。 关于配置优先级而言&#xff0c; application.properties>application.yml>application.yaml 另外JAVA程序程序还支持java系统配置和命令行…

lombok启动不生效(什么方法都试了,可还是不生效怎么办 ?! 救救我)

使用IntelliJ IDEA 2021.1.3&#xff08;Ultimate Edition&#xff09;时提示Lombok不生效 java: You aren’t using a compiler supported by lombok, so lombok will not work and has been disabled. 方式一&#xff1a;我们手动更新一下版本到以下版本 <!--Lombok--&…

水果音乐制作软件fl studio v21.1.0.3713 中文特别版

水果音乐制作软件fl studio v21.1.0.3713 中文特别版是一个功能完备的音乐制作环境&#xff0c;能够进行多轨道音频录制、音序处理和混音&#xff0c;可以帮助用户创作专业质量的音乐轨道。 借助 VST 托管、灵活的混音器、高级 MIDI 和 ReWire 支持&#xff0c;您将轻松驾驭各种…

第14章——FreeRTOS信号量

1.信号量的简介 信号量是一种解决同步问题的机制&#xff0c;可以实现对共享资源的有序访问。 信号量&#xff1a;用于传递状态&#xff08;区别于队列传递消息&#xff09; 信号量的计数值都有限制&#xff1a;限定最大值。 如果最大值被限定为1&#xff0c;那么它就是二值…

多种编程语言运行速度排名-10亿次除7求余数为0的数量

最佳方式是运行10次&#xff0c;取平均数&#xff0c;用时秒数显示3位小数。 因为第一次打开&#xff0c;可能CPU还没优化好&#xff0c;多次取平均&#xff0c;比较准确 第1次共10次&#xff0c;用时3秒&#xff0c;平均3秒 第2次共10次&#xff0c;用时4秒&#xff0c;平均3.…

搭建开发环境-操作系统篇(一键搭建开发环境)

概述 所谓工欲善其事必先利其器&#xff0c;搭环境往往是开发过程中卡出很多初学者的拦路虎。 对于很多老鸟来说&#xff0c;很多东西都已经习惯成自然&#xff0c;也就没有刻意和初学者说。但对于很多初学者&#xff0c;却是受益良多。 这个系列&#xff0c;先从操作系统开始…

string类写时拷贝

文章目录 1.string类拷贝构造函数的现代写法2.string类写时拷贝vs和g下string结构的不同vs下string的结构&#xff1a;g下string的结构 3.总结 1.string类拷贝构造函数的现代写法 string类拷贝构造函数的传统写法&#xff1a; string(const string& s){if (this ! &s)…

2023年每天都投递很多份简历,但都石沉大海,我还投吗?测试人该何去何从?

各大互联网公司的接连裁员&#xff0c;政策限制的行业接连消失&#xff0c;让今年的求职雪上加霜&#xff0c;想躺平却没有资本&#xff0c;还有人说软件测试岗位饱和了&#xff0c;对此很多求职者深信不疑&#xff0c;因为投出去的简历回复的越来越少了。 另一面企业招人真的…

计算机视觉--利用HSV和YIQ颜色空间处理图像噪声

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天我们将利用HSV和YIQ颜色空间处理图像噪声。在本次实验中&#xff0c;我们使用任意一张图片&#xff0c;通过RGB转HSV和YIQ的操作&#xff0c;加入了椒盐噪声并将其转换回RGB格式&#xff0c;最终实现对图像的噪声处理…

mysql之host is blocked问题

程序上线一段时间之后&#xff0c;更新程序总是遇到这个问题 每次都是重启几次程序&#xff0c;或者执行 flush hosts; 毕竟指标不治本&#xff0c;抽出时间决定分析一下问题&#xff0c;查阅了几篇博客。&#xff08;感谢这几位大佬&#xff09; https://blog.51cto.com/u_…

飞机打方块(四)游戏结束

一、游戏结束显示 1.新建节点 1.新建gameover节点 2.绑定canvas 3.新建gameover容器 4.新建文本节点 2.游戏结束逻辑 Barrier.ts update(dt: number) {//将自身生命值取整let num Math.floor(this.num);//在Label上显示this.num_lb.string num.toString();//获取GameCo…

数据结构—队列

队列 队列的概念及结构队列的实现 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 。 入队列&#xff1a;进行插入操作的一端称为队尾。 出队列&am…

Day8 智慧商城

项目演示 项目收获 创建项目 调整初始化目录 1.删components里的所有文件 2.删views里的所有文件 3.router/index.js 删路由 删规则 import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({routes: [] })export default route…

软件开发合同范本word文档,《某公司软件开发合同》,15页范本供参考

上一篇介绍了软件生命周期全过程&#xff0c;软件工程全周期全过程20项文档模板&#xff0c;附下载。从《合同》到《需求规格说明书》到软件设计、开发、实施、验收、维护等全过程相关文档模板。有朋友反馈附件内容没有补全&#xff0c;本次及后续会用实际案例补全附件内容&…

Backblaze 2023 Q2 硬盘故障质量报告解读

Backblaze 在其博客上发布了 2023 年第二季度的存储设备统计数据。这些数据包括了 Backblaze 在该季度所拥有的存储设备的数量、故障率和更换率等信息&#xff0c;这些信息对于了解存储设备的可靠性和性能非常有用。 在最新的Backblaze硬盘使用统计报告中&#xff0c;我们看到了…

OLED透明屏介绍:领先科技的革命性创新

OLED透明屏作为一项领先的科技创新&#xff0c;在产品设计和用户体验方面展现出了巨大的潜力。 在这篇文章中&#xff0c;尼伽将介绍OLED透明屏的定义、特点、应用领域以及未来发展趋势&#xff0c;以帮助您全面了解OLED透明屏。 一、OLED透明屏的定义与原理 1.1 定义&#x…

概念解析 | 走进射线管积分:探索数学与现实世界的神秘桥梁

注1&#xff1a;本文系“概念解析”系列之一&#xff0c;致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是&#xff1a;射线管积分。 走进射线管积分&#xff1a;探索数学与现实世界的神秘桥梁 射线管积分雷达成像 射线管积分&#xff08;Ray Tube Integration&a…

leetcode 188. 买卖股票的最佳时机 IV

2023.8.21 这道题是 买卖股票的最佳时机III 的升级版&#xff0c;即买卖次数限制为k次&#xff0c;做法和上一篇如法炮制&#xff0c;直接看代码&#xff1a; class Solution { public:int maxProfit(int k, vector<int>& prices) {vector<vector<int>>…