整数分解方法

article/2025/11/11 1:45:42

题目大意:给定一个整数n,找到k个数,使得其和等于n。
如:

4=1+1+1+1
4=1+1+2;
4=1+3;
4=2+2;
4=4;

求其分解的所有可能,并输出分解表达式。
解题思路:要拆分整数n,肯定先要找到一个元素,然后我们会发现,剩下的问题还是一个整数差分问题,因此容易得到问题的解。
定义函数f(n)为n可以拆分的解的个数,即可以先拆分出一个数字k(k = 1,2,……,n),然后再拆分f(k),可以得出有:

n=1+f(n-1);
n=2+f(n-2);
·····
n=(n-1)+f(1);
n=n+f(0)

f(n)=f(n1)+f(n2)++f(1)+f(0)(f(0)=1) f ( n ) = f ( n − 1 ) + f ( n − 2 ) + … … + f ( 1 ) + f ( 0 ) ( 其 中 f ( 0 ) = 1 ) 公 式 ①

数学公式推导:
f(n+1)=f(n)+f(n1)++f(2)+f(1) f ( n + 1 ) = f ( n ) + f ( n − 1 ) + … … + f ( 2 ) + f ( 1 ) 公 式 ②

②-①
f(n+1)f(n)=f(n)f(0) f ( n + 1 ) − f ( n ) = f ( n ) − f ( 0 )

f(n+1)=2f(n)1 f ( n + 1 ) = 2 f ( n ) − 1

f(n+1)1=2[f(n)1] f ( n + 1 ) − 1 = 2 [ f ( n ) − 1 ]

于是可以解得
f(n)=2(n1)n>=1 f ( n ) = 2 ( n − 1 ) , n >= 1

在来想一想该用怎样的数据结构来存储描述,用数组,int res[max]用来暂存拆分元素。先拿简单的拆分来说事,拆分成两个数的情况。
这里写图片描述
如何输出这拆分的表达式,看一眼就很明,循环1~n,输出即可。

//只拆分为两个数的时候
void resolve(int n)
{ //res用来暂存拆分元素//p是游标,初始值为p=0;for(int i=1;i<=n;i++){res[p]=i;p++;//下一个位置存储n-i;res[p]=n-i;//输出处理p--;//回归到起点。}
}

分析上面的代码,再来看递推,如果分成三个数,那么在即将执行res[p]=n-i时,需要将n-i在一次分解成两个数,即resolve(n-i),这样就形成了递归。
那么递归的出口条件是什么呢,当需要分解的数是0时,已经不能在继续往下分了,所以递归出口就是
if(n<=0), 当进入递归出口的时候,表明本次已经分解完成,可以输出res中的数据。

整理上诉得到递归处理函数代码如下

void resolve(int n)
{ if(n<=0){   for (int i=0; i<p_res; i++)  //输出 cout << res[i] << " ";  cout << endl;  return ;}for(int i=1;i<=n;i++){res[p]=i;p++;resolve(n-i);p--;}
}

贴上可运行代码


#include <iostream>  
using namespace std;  
#define MAX 20  
int res_num;  
// 拆分元素暂存在res数组中  
int res[MAX];  
int p = 0;   
// 将n进行拆分  
void resolve(int n);  int main() {  while (1) {  int n;  cin >> n;  resolve(n);  cout << "total num of res:\t" << res_num << endl;  res_num = 0;  }  return 0;  
}  void resolve(int n) {  if (n<=0) { // 出口  for (int i=0; i<p; i++)  cout << res[i] << " ";  cout << endl;  res_num++;  }  for (int i=1; i<=n; i++) {  res[p] = i;  p++;        // p ++来顺序存储各个拆分元素  resolve(n-i);  p--;        // 此行必须有,执行完这一行,下一次for循环才能回退  }  
}  

测试结果如下:
这里写图片描述
可以发现上述代码输出的结果有重复答案,如当n=4时,会输出1 3,和3 1两组解,其实他们是相同的。

如果要求答案不能重复呢?

同样,我们可以定义一个函数f(n, min_factor),其中min_factor表示n拆分后元素中的最小值,这样即可通过min_factor来限制for循环的初始值,达到拆分元素从小到大输出的目的,从而避免相同的解重复输出

稍微修改上述代码,即可得到解。
贴出完整可运行代码如下:

#include <iostream>  
using namespace std;   
#define MAX 20  
int res_num;  
// 拆分元素暂存在res数组中  
int res[MAX];  
int p = 0;  // 将n进行拆分 
void resolve(int n, int min_factor=1);  int main() {  while (1) {  int n;  cin >> n;  resolve(n,1);  cout << "total num of res:\t" << res_num << endl;  res_num = 0;  }  return 0;  
}  void resolve(int n, int min_factor) {  if (n<=0) { // 出口  for (int i=0; i<p; i++)  cout << res[i] << " ";  cout << endl;  res_num++;  }  for (int i=min_factor; i<=n; i++) {     // 此处修改  res[p] = i;  p++;        //  p ++来顺序存储各个拆分元素  resolve(n-i, i);// 此处修改  p--;        //  // 此行必须有,执行完这一行,下一次for循环才能回退  }  
}  

这里写图片描述




附加类似练习
将一个数n的分解为因子的乘积形式,输出所有可能,并输出表达式。
12=2*2*3;
12=2*6;
12=3*4;
12=6*2;
12=12*1;
解法与上述大同小异,不在累述。
代码如下

#include<iostream>
using namespace std;
int data[100];
int p=0;
int num=0; 
int x;
void resolve(int n,int min)
{if(n<2) {num++;cout<<x<<"=";for(int j=0;j<p;j++){cout<<data[j];if(j!=p-1)cout<<"*";if(data[j]==x)cout<<"*1";}cout<<endl;return ;}for(int i=min;i<=n;i++){if(n%i==0){data[p]=i;p++; resolve(n/i,i);p--;        }}
}
int main()
{while(cin>>x){resolve(x,2);cout<<"The totla num is  "<<num<<endl;cout<<"--------------------------"<<endl;}
}

这里写图片描述

【动态规划求解分解整数的总的可能情况数】
1、问题描述和分析
对于一个正整数n的分化,就是把n表示成一系列正整数之和的表达式。注意,分划与顺序无关,例如6=1+5 和 6=5+1被认为是同一个划分。另外,这个整数n本身也算是一种分化。
分析:
所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+…+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,…,mi}为n的一个划分。
如果{m1,m2,…,mi}中的最大值不超过m,即max(m1,m2,…,mi)<=m,则称它属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);
例如但n=4时,他有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
2、数据结构和算法
该问题是求出n的所有划分个数,即f(n, m)。下面我们考虑求f(n,m)的方法,采用递归法, 根据n和m的关系,考虑以下几种情况:
(1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
(2)当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,…,1};
(3)当n=m时,根据划分中是否包含n,可以分为两种情况:
(a)划分中包含n的情况,只有一个即{n};
(b)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此 f(n,n) =1 + f(n,n-1);
(4)当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);
(5)但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
(a)划分中包含m的情况,即{m, {x1,x2,…xi}}, 其中{x1,x2,… xi} 的和为n-m,因此这情况下为f(n-m,m);
(b)划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);
因此 f(n, m) = f(n-m, m)+f(n,m-1);
综上所述:
这里写图片描述

#include<stdio.h>
int Divintege(int n,int m)
{
if(n==1||m==1)return 1;
else if(n<m)return Divintege(n,n);
else if(n==m)return 1+Divintege(n,n-1);
elsereturn Divintege(n,m-1)+Divintege(n-m,m);
}int  main(void)
{int n;while(scanf("%d",&n)!=EOF&&(n>=1)){printf("%d\n",Divintege(n,n));}return 0;
}

http://chatgpt.dhexx.cn/article/qOEjha20.shtml

相关文章

史上最全的整数分解方法(包含经典的分苹果问题)

【华为OD机试真题 2022&2023】真题目录 点这里 【华为OD机试真题】信号发射和接收 &试读& 点这里 【华为OD机试真题】租车骑绿道 &试读& 点这里 整数分解方法总结 一、加法分解&#xff1a; 题目描述&#xff1a; 给定一个正整数&#xff0c;我们可以…

js输出1-100之间所有的质数并求总个数

代码如下&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><meta http-equiv"X-UA-Compa…

JavaScript输出杨辉三角形

JavaScript输出杨辉三角形 杨辉三角形的特点和规律代码如下&#xff1a;结果 杨辉三角形的特点和规律 起始行为第0行&#xff0c;第N行为N1个数从 N > 2行开始&#xff0c;每一行的数值&#xff08;不包含两边的数值&#xff09;都是上一行两个数字的相加。当 J1 或 JN1时&…

Vscode中JS输出乱码问题的解决

一直很好用vscode突然不好用了&#xff0c;原来输出正常的JS代码在输出中都是乱码。于是上网查答案&#xff0c;试了很多奇奇怪怪的答案&#xff0c;然而没有一款能够解决我这个问题。仔细琢磨&#xff0c;既然以前好用&#xff0c;现在不好用&#xff0c;应该是某个电脑操作“…

js输出九九乘法表

js输出九九乘法表 控制台输出 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…

利用Javascript输出多个图片

利用Javascript输出多个图片 如果不利用Js输出图片的话&#xff0c;利用HTMLCSS输出多个图片非常麻烦的&#xff0c;工作量庞大。 建议遇到有必要多个输出的图片&#xff0c;使用js是最好的方法。 <script>var i;var arr["<img src./img/1.jpg>","…

js实现图形输出

1、矩形 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><script>//嵌套循环:外层循环一次&#xff0c;内层循环一轮//矩形for (var j 1; j < 5; j) {for (var i 1; …

用JS 输出 正三角形

效果图 以下是代码及 每行代码解释&#xff0c;仅供参考。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"view…

js 页面输出html,javascript中如何输出?

面对刚刚学习JavaScript的同学们&#xff0c;你是否知道JavaScript如何输出&#xff1f;下面本篇文章就来给大家介绍一下javascript的几种输出方式&#xff0c;希望对大家有所帮助。 JavaScript的输出方式&#xff1a; javascript 没有任何打印或输出的函数&#xff0c;可以通过…

js 向页面输出html,javascript怎么输出?

JavaScript怎么输出&#xff1f;输出方式有哪些&#xff1f;下面本篇文章就给大家介绍JavaScript的几种输出方式&#xff0c;希望对大家有所帮助。 方法1&#xff1a;使用window.alert()进行输出 window.alert()方法用于显示带有一条指定消息和一个【确认】 按钮的警告框。 代码…

JS 的三种输出方式

输出方式 第一种&#xff1a;alert&#xff08;&#xff09; alert() 语句&#xff1a;可以输出警告框。具有弹框效果 代码示例&#xff1a; <script type"text/javascript">alert(holle warold); </script> 效果图&#xff1a; 第二种&#xff1a;…

JavaScript的输出方式大全

helo&#xff01;小伙伴们&#xff0c;你们是不是和我一样学在学js过程中感觉这个知识不仅脑子&#xff0c;反而觉得相关的知识好多呀&#xff0c;网上的文章和视频也是&#xff0c;都不知道该怎么选了&#xff0c;没关系&#xff0c;我们慢慢来&#xff0c;这些知识点一点一点…

JS输出方式

一个程序编写完成之后&#xff0c;我们运行出的结果也有着不同的输出方式。 下面我主要介绍三种输出结果的方式&#xff1a;alert&#xff1b;console.log&#xff1b;document.write。 alert 这种输出方式是使用弹出框显示结果&#xff0c;但是只能一个一个的输出&#xff…

Android LiveData我的理解

LiveData用大众语言来来讲&#xff0c;是一个被观察者&#xff0c;也是一个数据持有类或者可以称为一个数据的包裹类。它有别于其他的观察者的重点是&#xff0c;他具有生命周期感知能力&#xff0c;这里生命周期指的是activities, fragments, or services 的生命周期。 讲到L…

Android LiveData组件详解以及LiveDataBus

转载请标明出处&#xff1a;https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自【赵彦军的博客】 文章目录 LiveData简介使用Java 使用方式两种订阅模式observeobserveForever 三、LiveDataBus3.1 为什么要用LiveDataBus替代EventBus和RxBus?3.2 LiveDataB…

【Android】MutableLiveData与LiveData

MutableLiveData笔记 MutableLiveData是什么&#xff1f;LiveData是什么&#xff1f;LiveData常用的方法MutableLiveData和LiveData的区别 关于postValue和setValue的机制简单理解 MutableLiveData是什么&#xff1f; public class MutableLiveData extends LiveData<T>…

Android架构——LifeCycle和LiveData原理学习总结

本文是楼主学习LifeCycle和LiveData原理的一些总结&#xff0c;本文不会长篇分析源码&#xff0c;而是利用类图和总结性的文字归纳原理。由于Livedata和LifeCycle有紧密联系&#xff0c;所以本文先总结LifeCycle原理&#xff0c;再总结LifeData原理。 本文LifeCycle基于版本an…

Android架构之LiveData组件

Jetpack组件系列文章 Android架构之LifeCycle组件 Android架构之Navigation组件(一) Android架构之Navigation组件(二) Android架构之Navigation组件(三) Android架构之Navigation组件(四) Android架构之ViewModel组件 Android架构之LiveData组件 Android架构之Room组件(一) An…

LiveData的基本使用

我们在《ViewModel的基本使用》这篇文章中提到了&#xff0c;ViewModel的主要作用是存放页面所需要的各种数据&#xff0c;而当这些数据发生变化时&#xff0c;我们采用接口的方式实现对页面的通知。 这样做是可行的&#xff0c;但如果要观察的数据很多&#xff0c;则需要定义大…

DataBinding与LiveData

DataBinding 一、添加配置二、使用修改布局文件具体使用单向绑定、方法绑定双向绑定、加载网络图片例子Adapter中使用使用 ObservableField 一、添加配置 如果需要使用databinding 需要在gradle中添加如下配置 defaultConfig {......//开启dataBindingdataBinding {enabled …