当前位置: 首页 > news >正文

传智杯 第六届—第二场—D

题目描述:

        小红拿到了一个数组,她想取一些数使得取的数之和尽可能大,但要求这个和必须是 k k\ k  的倍数。你能帮帮她吗?

输入描述:

        第一行输入两个正整数 n  和 k 。第二行输入 n 个正整数 ai 。(1≤n,k≤10^3,1≤ai​≤10^10)

输出描述:

        如果没有合法方案,输出 -1;否则输出最大的和。

示例1

输入:

5 5
4 8 2 9 1

输出:

20

说明:

        取后四个数即可。

想法1:暴力方法

        最终运行超时,由于循环次数过大。设置一个二维数组,每个一维数组代表在第i个正整数出现过后,会有的和的所有情况,相较于上次(即上个正整数),这次和的情况为上次的两倍,分别是在之前的情况下再分别加x和不加x的两种情况,并将这所有的情况都存储在该正整数所对应的数组中,再下次的情况又*2。所以最终的情况将是2^n,当n很大的时候,这个值将非常的大,所以会导致运行超时。其中第一个一维数组含有的数据个数为2(1*2),第二个一维数组含有的数据个数为4(2*2),第三个一维数组含有的数据个数为8(4*2)........第n个一维数组含有的数据个数为2^n(2^(n-1)*2)。

代码:

#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
vector <long long>sum[1001];    //用于保存和
int  main()
{//输入int n, k;   //正整数个数,倍数cin >> n >> k;long long max = 0;long long* a = new long long[n];for (int i = 0;i < n;i++){cin >> a[i];if (i == 0){sum[i].push_back(0);sum[i].push_back(a[i]);continue;}//记录下所有和的情况for (int j = 0;j < pow(2, i);j++)    //不加a[i]{sum[i].push_back(sum[i-1][j]);if (sum[i][j] % k == 0)   //可以被整除{max = max > sum[i][j] ? max : sum[i][j];}}for (int j = 0;j < pow(2, i);j++)    //加a[i]{sum[i].push_back(sum[i - 1][j] + a[i]);if (sum[i][j + pow(2, i)] % k == 0)   //可以被整除{max = max > sum[i][j] ? max : sum[i][j + pow(2, i)];}}sum[i - 1].clear();}//输出cout << (max != 0 ? max : -1)<<endl;system("pause");return 0;
}

想法2:优化 

        在想法1的基础上,能不能减少循环的次数进行优化。我们可以考虑将每个正整数所含的一维数组变成定量的,可以将每个一维数组设置成k个空间,即将每次的结果保留在以sum%k为下标的数组对应位置,即每次更新对应位置的值,以示例1为例,其二维数组的结果是:

其中n=5;k=5,则会分配5*5的二维数组,行为第i个正整数,列为取余为j余0     余1     余2     余3     余4
+4       0       0       0       0       4
+8       0       0       12      8       4
+2       10      6       12      8       14
+9       15      21      17      23      19
+1       20      21      22      23      24

        将上一个一维数组的值+这次的正整数的值所得到的新值写到取余过后的正确位置,并将其与上次的值进行比较,取更大的值,并保存在数组中,直到最后一次计算结束,就可以得到取余为0的最大值。 

代码:

#include<iostream>
using namespace std;
int  main()
{//输入int n, k;   //正整数个数,倍数cin >> n >> k;long long* a = new long long[n];long long sum[1000][1000];    //用于保存for (int i = 0;i < n;i++){cin >> a[i];if (i == 0){sum[i][a[i] % k] = a[i];continue;}for (int j = 0;j < k;j++)    //不加x{sum[i][j] = sum[i - 1][j];}for (int j = 0;j < k;j++)    //加x{sum[i][(a[i] + sum[i - 1][j]) % k] = max(a[i] + sum[i - 1][j], sum[i-1][(a[i] + sum[i - 1][j]) % k]);}}//输出cout << (sum[n - 1][0] != 0 ? sum[n - 1][0] : -1) << endl;system("pause");return 0;
}


http://www.mrgr.cn/news/55699.html

相关文章:

  • WPF实现类似网易云音乐的菜单切换
  • Web Storage:数据储存机制
  • 记录:网鼎杯2024赛前热身CRYPT01密码学
  • 目标检测系统【环境详细配置过程】(CPU版本)
  • 计算DOTA文件的IOU
  • 重构复杂简单变量之用子类替换类型码
  • 【前端】如何制作一个自己的网页(13)
  • Redis 集群
  • 01,hana
  • 开源EMO再升级!复旦|百度|南大推出Hallo2,可以生成4K,一小时的音频驱动的视频。
  • AGV电子地图之贝塞尔曲线
  • 每日OJ题_牛客_[NOIP2001]装箱问题_01背包_C++_Java
  • 面试总结(持续更新~)
  • 100多种【基于YOLOv8/v10/v11的目标检测系统】目录(python+pyside6界面+系统源码+可训练的数据集+也完成的训练模型)
  • pychar社区版下载
  • Leetcode|24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II
  • 01 一篇读懂25机械考研复试超全流程讲解|考研面试经验和面试真题快来背诵!
  • 内网穿透frp部署
  • Spring Boot慢启动?一文带你轻松优化!
  • 【Linux】线程基本概念,线程控制
  • 深度学习--CNN实现猫狗识别二分类(附带下载链接, 长期有效)
  • [while循环]k的幂
  • js实现两个变量交换
  • 座舱软件开发“道与术”
  • 04,perl
  • navigate连接opengauss