UncleFather » 09 сен 2016 14:43, Пт
Java, разбиениe числа на слагаемые
Задача 1. Выведем количество разбиений числа
Примечание: Разбиение числа n — это представление n в виде суммы положительных целых чисел, называемых частями. При этом порядок следования частей не учитывается.
Не путаем разбиение с композицией!
Итак, для подсчета количества разбиений числа, воспользуемся рекуррентной формулой из Википедии (см. ссылку выше):
- 01.jpg (7.07 КБ) 4525 просмотров
с начальными значениями:
- 02.jpg (4.55 КБ) 4525 просмотров
java:
Код: Выделить всё
import java.util.Scanner;
public class Slagaemye {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
System.out.println(slag(iVol , iVol));
}
static int slag(int n, int k) {
if (n > 0 && k == 0) return 0;
if (n == 0 && k == 0) return 1;
if (k > n) return slag(n, n);
return slag(n, k-1) + slag(n-k, k);
}
}
Задача 2. Выведем количество разбиений числа для неповторяющихся слагаемых
Алгоритм аналогичен предыдущей задаче, за исключением одного из рекурсивных вызовов в последней строке.
java:
Код: Выделить всё
import java.util.Scanner;
public class Slagaemye_nepovtor {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
System.out.println(slag(iVol , iVol));
}
static int slag(int n, int k) {
if (n > 0 && k == 0) return 0;
if (n == 0 && k == 0) return 1;
if (k > n) return slag(n, n);
return slag(n, k-1) + slag(n-k, k-1);
}
}
Задача 3. Выведем все разбиения числа
java:
Код: Выделить всё
import java.util.Scanner;
public class Slagaemye {
static int[] iArr = new int[100];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
currSlag(iVol, iVol, 0);
}
static void currSlag(int n, int k, int i) {
if ( n < 0 ) return;
if ( n == 0 ) {
for (int j = 0; j < i; j++) System.out.print(iArr[j] + " ");
System.out.println();
}
else {
if ( n >= k) {
iArr[i] = k;
currSlag(n - k, k, i + 1);
}
if ( k > 1) currSlag(n, k - 1, i);
}
}
}
Задача 4. Выведем все разбиения числа с неповторяющимися слагаемыми
Опять же, предыдущий алгоритм почти полностью сохраняется, за исключением первого условия и одного из рекурсивных вызовов в процедуре.
java:
Код: Выделить всё
import java.util.Scanner;
public class Slagaemye_nepovtor {
static int[] iArr = new int[100];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
currSlag(iVol, iVol, 0);
}
static void currSlag(int n, int k, int i) {
if ( n < 0 || k < 0 ) return;
if ( n == 0 ) {
for (int j = 0; j < i; j++) System.out.print(iArr[j] + " ");
System.out.println();
}
else {
if ( n >= k) {
iArr[i] = k;
currSlag(n - k, k - 1, i + 1);
}
if ( k > 1) currSlag(n, k - 1, i);
}
}
}
По данной теме дополнительно смотрим статью в разделе «олимпиады по программированию на Физтехе» на сайте МФТИ Лекция 6. Задача разложения числа на слагаемые. Задача подсчета и генерации и обсуждение Разложение числа на неповторяющиеся слагаемые на сайте CyberForum.ru.
[size=150][b][color=#80FF00]Java, разбиениe числа на слагаемые[/color][/b][/size]
[b][size=150]Задача 1. Выведем количество разбиений числа[/size][/b]
[url=https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D0%B1%D0%B8%D0%B5%D0%BD%D0%B8%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0]Примечание: Разбиение числа n — это представление n в виде суммы положительных целых чисел, называемых частями. При этом порядок следования частей не учитывается.[/url]
Не путаем разбиение с [url=https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D1%8F_%D1%87%D0%B8%D1%81%D0%BB%D0%B0]композицией[/url]!
Итак, для подсчета количества разбиений числа, воспользуемся рекуррентной формулой из Википедии (см. ссылку выше):[attachment=1]01.jpg[/attachment]с начальными значениями:[attachment=0]02.jpg[/attachment]
[size=85][i]java:[/i][/size]
[code]import java.util.Scanner;
public class Slagaemye {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
System.out.println(slag(iVol , iVol));
}
static int slag(int n, int k) {
if (n > 0 && k == 0) return 0;
if (n == 0 && k == 0) return 1;
if (k > n) return slag(n, n);
return slag(n, k-1) + slag(n-k, k);
}
}[/code]
[hr][/hr]
[b][size=150]Задача 2. Выведем количество разбиений числа для неповторяющихся слагаемых[/size][/b]
Алгоритм аналогичен предыдущей задаче, за исключением одного из рекурсивных вызовов в последней строке.
[size=85][i]java:[/i][/size]
[code]import java.util.Scanner;
public class Slagaemye_nepovtor {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
System.out.println(slag(iVol , iVol));
}
static int slag(int n, int k) {
if (n > 0 && k == 0) return 0;
if (n == 0 && k == 0) return 1;
if (k > n) return slag(n, n);
return slag(n, k-1) + slag(n-k, k-1);
}
}
[/code]
[hr][/hr]
[b][size=150]Задача 3. Выведем все разбиения числа[/size][/b]
[size=85][i]java:[/i][/size]
[code]import java.util.Scanner;
public class Slagaemye {
static int[] iArr = new int[100];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
currSlag(iVol, iVol, 0);
}
static void currSlag(int n, int k, int i) {
if ( n < 0 ) return;
if ( n == 0 ) {
for (int j = 0; j < i; j++) System.out.print(iArr[j] + " ");
System.out.println();
}
else {
if ( n >= k) {
iArr[i] = k;
currSlag(n - k, k, i + 1);
}
if ( k > 1) currSlag(n, k - 1, i);
}
}
}
[/code]
[hr][/hr]
[b][size=150]Задача 4. Выведем все разбиения числа с неповторяющимися слагаемыми[/size][/b]
Опять же, предыдущий алгоритм почти полностью сохраняется, за исключением первого условия и одного из рекурсивных вызовов в процедуре.
[size=85][i]java:[/i][/size]
[code]import java.util.Scanner;
public class Slagaemye_nepovtor {
static int[] iArr = new int[100];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int iVol = sc.nextInt();
currSlag(iVol, iVol, 0);
}
static void currSlag(int n, int k, int i) {
if ( n < 0 || k < 0 ) return;
if ( n == 0 ) {
for (int j = 0; j < i; j++) System.out.print(iArr[j] + " ");
System.out.println();
}
else {
if ( n >= k) {
iArr[i] = k;
currSlag(n - k, k - 1, i + 1);
}
if ( k > 1) currSlag(n, k - 1, i);
}
}
}[/code]
По данной теме дополнительно смотрим статью в разделе «олимпиады по программированию на Физтехе» на сайте МФТИ [url=http://acm.mipt.ru/twiki/bin/view/Curriculum/FIVTLecturesTerm1Lecture6]Лекция 6. Задача разложения числа на слагаемые. Задача подсчета и генерации[/url] и обсуждение [url=http://www.cyberforum.ru/algorithms/thread1332619.html]Разложение числа на неповторяющиеся слагаемые[/url] на сайте CyberForum.ru.