首页 > 其他分享 >2024.8.31杂记

2024.8.31杂记

时间:2024-08-31 16:03:24浏览次数:4  
标签:10 2024.8 31 back int vector 杂记 ans path

P1249 最大乘积

题目描述

一个正整数一般可以分为几个互不相同的自然数的和,如 \(3=1+2\),\(4=1+3\),\(5=1+4=2+3\),\(6=1+5=2+4\)。

现在你的任务是将指定的正整数 \(n\) 分解成若干个互不相同的自然数(也可以不分解,就是这个数字本身)的和,且使这些自然数的乘积最大。

输入格式

只一个正整数 \(n\),(\(3 \leq n \leq 10000\))。

输出格式

第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。

第二行是最大的乘积。

样例

输入样例 #1

10

输出样例 #1

2 3 5
30

解题思路

这里取自 离散小波变换° 的动态规划解法。

题目描述中“一个正整数一般可以分为几个互不相同的自然数的和”,也就是将自然数 \(n\) 拆解为若干个互不相同的数进行乘法运算得到最大的分解方案,输出分解方案及乘积结果。

那么将其视为 \(01\) 背包问题,即从 \(1\) 到 \(n\) 中选择若干数使其和为 \(n\) 且乘积最大,但是背包问题中的价值是进行加法运算得到的,这是我们需要将乘积转换为加法运算,对数中有一个很好的性质,即 \(lna+lnb=ln(ab)\),因此我们取每个数的对数为价值,而体积为数本身,在转移过程中记录方案,最后根据方案进行大数乘小数的高精度运算。

C++代码

#include <bits/stdc++.h>
#include <sstream>
using namespace std;
const int N = 10010;
typedef long long LL;

vector<int> mul(vector<int> A, int B) {
	vector<int> C;
	int t = 0;
	for (int i = 0; i < A.size() || t; i++) {
		if (i < A.size())
			t += A[i] * B;
		C.push_back(t % 10);
		t /= 10;
	}
	while (C.size() > 1 && C.back() == 0)
		C.pop_back();
	return C;
}

vector<int> intToVector(int x) { // x > 0
	vector<int> X;
	while (x) {
		X.push_back(x % 10);
		x /= 10;
	}
	return X;
}

int n;
double f[N], v[N]; // v 为价值
int w[N], path[N]; // path 存储路径
vector<int> ans; // 存储最终方案

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) { // 初始化
		w[i] = i;
		v[i] = log(i);
	}
	for (int i = 1; i <= n; i++)
		for (int j = n; j >= i; j--) {
			if (f[j - w[i]] + v[i] > f[j]) { // 滚动数组
				f[j] = f[j - w[i]] + v[i];
				path[j] = j - w[i];
			}
		}
	for (int i = n; i; i = path[i])
		ans.push_back(i - path[i]);
	sort(ans.begin(), ans.end());
	vector<int> res;
	res.push_back(1);
	for (int i = 0; i < ans.size(); i++) {
		res = mul(res, ans[i]);
		cout << ans[i] << ' ';
	}
	cout << endl;
	for (int i = res.size() - 1; i >= 0; i--)
		cout << res[i];
	return 0;
}

标签:10,2024.8,31,back,int,vector,杂记,ans,path
From: https://www.cnblogs.com/Cocoicobird/p/18390413

相关文章

  • 2024年8月31日 Python - asycnio
    参考asyncio---异步I/O—Python3.12.4文档asyncio视频教程-bilibili6.2.9. yield表达式—Python3.12.4文档PEP380:委托给子生成器的语法yield介绍yieldx生成一个内容yieldfrom委托给子生成器,yieldfromiterable本质上只是foritemini......
  • 滑动窗口系列(定长滑动窗口长度)8/31
    1.长度为K子数组中的最大和给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:子数组的长度是 k,且子数组中的所有元素 各不相同 题意:在之前题目的基础上添加了一个条件:子数组中的所有元素各不相同。因此在这里使......
  • 2024/08/31 每日一题
    LeetCode3127构造相同颜色的正方形方法1:模拟classSolution{publicbooleancanMakeSquare(char[][]grid){for(inti=0;i<2;i++){for(intj=0;j<2;j++){intcnt=0;//统计黑色数量cnt+=......
  • 2024.8.30 总结(集训 考 DP)
    上午三个多小时考四道题的DP。赛时会的分:[100](?)+100+[30](?)+100。估分:100+100+0+100。实际分:10+100+0+100。挂巨量的分,挂了120分。下面是一些值得注意的点:T1就是分组背包。DP数组下标要考虑负数可以直接全体加一个值变成非负的,[或者用map之类的](?)(&不......
  • VBA语言専攻简介0831
    VBA语言専攻简介0831在当今世界,几乎没有任何工作是没有计算机的。有些工作需要定期重复相同的过程,最好将它们自动化。一旦任务自动化,只需单击一个按钮即可运行。VBA是实现自动化工作的最为简单的方式,它不需要其他工具,因为它已经与MicrosoftOffice软件集成。VBA是VisualBasicfor......
  • 2024.8.29 总结
    上午&中午按计划学了李超线段树,照着题解写过了模板题。然后本来打算去做题单里的一道Ynoi紫来练dsuontree,于是边写题解边想,结果写着写着就不会了,发现好像dsuontree不太好做,好像是两只log的。还可能大概会一个单log大常数线段树合并。看题解区发现有跑出dfs序后......
  • 2024.8.24-美团
    第3题-塔塔商店线段树,因为需要返回区间最大值的id,所以对于建树、更新、检索部分需要进行修改#include<bits/stdc++.h>usingnamespacestd;#definelcp<<1#definercp<<1|1constintN=1e5+5;intc[N];structsegtree{structnode{intl,r,id;......
  • 2024.8.28 总结
    上午做了一个很板的广义SAM题,算是练了一下广义SAM,当时基本上能自己写出广义SAM了,但是还是写错了两个地方(好像是把p写成了q)。大概是做完这道题之后我去看了看lr的博客,发现他的博客里有计划。于是我也写了一个最近的计划。在这之后我就去挑了个较基础的SA题来写。后缀......
  • 信息学奥赛一本通1314:【例3.6】过河卒(Noip2002)
    【题目描述】棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n,......
  • 【力扣】3145.大数组元素的乘积
    题目描述一个非负整数 x 的 强数组 指的是满足元素为2的幂且元素总和为 x 的最短有序数组。下表说明了如何确定 强数组 的示例。可以证明,x 对应的强数组是独一无二的。数字二进制表示强数组100001[1]801000[8]1001010[2,8]1301101[1,4,8]2310111[1,2,4,16]......