Рекурсивные числа

index.htm - английский текст,

recnumb.zip - все программы,

 

Задача. Найдите такое 10-значное число, в котором первая слева цифра равняется количеству нулей в этом числе, вторая цифра равняется количеству единиц в этом числе, и так далее, десятая цифра равняется количеству девяток в этом числе.

Например, подходит число 6 210 001 000 . Действительно, в нем 6 нулей, 2 единицы, 1 двойка, 1 шестерка, и других цифр нет.

Задача обобщается для чисел произвольной разрядности.

Задача несколько раз мне встречалась в сборниках олимпиадных задач для 10-значного числа, при этом каждый раз приводился только ответ без решения.

Ответ в этой задаче достаточно любопытен.

Для 2-значных чисел - решений нет,
Для 3-значных чисел - решений нет,
Для 4-значных чисел - два решения - 1210 и 2020,
Для 5-значных чисел - одно решение - 21200,
Для 6-значных чисел - решений нет,
Для 7-значных чисел - одно решение - 3211000,
Для n-значных чисел, n>7 - одно решение -

n-4 , 2 , 1 , 0 , ... , 0 , 1 , 0 , 0 , 0 .

Решаем задачу при помощи суперкомпилятора.

Исходная программа на Яве:

class RecNumb {
    public static final int nofDigits = 5;

    static class State {
        int[] digits = new int[nofDigits];

        State (int[] digits) {
            for (int i=0; i<nofDigits; i++) {
                this.digits[i] = digits[i];
            }
        }
    }

    public static void main (String args[]) throws Exception {
        int[] digits = { 2, 1, 2, 0, 0};
        checkAndPrint (digits);
    }

    public static void checkAndPrint(int[] digits1) throws Exception {
        int[] digits = new int[nofDigits];

        for (int i=0; i<nofDigits; i++) {
            digits[i] = digits1[i];
        }  

        State s = new State (digits);

        for (int i=0; i<nofDigits; i++) {
            int sum = iDigit(s, i);
            for (int j=0; j<nofDigits; j++) {
                if(iDigit(s, j)==i) sum--;
                if(sum<0) throw new Exception();
            }
            if(sum>0) throw new Exception();
        }
        
        String out = "";
        for (int i=0; i<nofDigits; i++) out = out + s.digits[i];
        System.out.println(out);
    }

    public static int iDigit(State s, int ia) throws Exception {
        for (int i=0; i<nofDigits; i++) {
            if (s.digits[ia]==i) {s.digits[ia]=i; return i;}
        }
        throw new Exception();
    }

 

nofDigits - задает разрядность чисел в примере.

Массив    int[] digits  служит для контрольного пуска на счет. В тех случаях, когда ответа нет, пуск бессмысленен.

В архивированном приложении - все примеры (они занумерованы по номерам примеров), здесь приведу остаточные программы - они маленькие.

nofDigits = 2 (решений нет) 

 
public static void checkAndPrint (final int[] digits1_1)
	  throws java.lang.Exception
	{
	  final int[] digits_2 = new int[2];
	  final int digits1_0_3 = digits1_1[0];
	  digits_2[0] = digits1_0_3;
	  final int digits1_1_6 = digits1_1[1];
	  digits_2[1] = digits1_1_6;
	  final int[] digits_14 = new int[2];
	  digits_14[0] = digits1_0_3;
	  digits_14[1] = digits1_1_6;
	  throw new java.lang.Exception();
	}
//---------------------------   0 sec - JScp version 0.1.22

 

nofDigits = 3 (решений нет) 

 
public static void checkAndPrint (final int[] digits1_1)
	  throws java.lang.Exception
	{
	  final int[] digits_2 = new int[3];
	  final int digits1_0_3 = digits1_1[0];
	  digits_2[0] = digits1_0_3;
	  final int digits1_1_6 = digits1_1[1];
	  digits_2[1] = digits1_1_6;
	  final int digits1_2_9 = digits1_1[2];
	  digits_2[2] = digits1_2_9;
	  final int[] digits_18 = new int[3];
	  digits_18[0] = digits1_0_3;
	  digits_18[1] = digits1_1_6;
	  digits_18[2] = digits1_2_9;
	  throw new java.lang.Exception();
	}
//---------------------   1 sec - JScp version 0.1.22

 

nofDigits = 4 (два решения) 

 
public static void checkAndPrint (final int[] digits1_1)
	  throws java.lang.Exception
	{
	  final int[] digits_2 = new int[4];
	  final int digits1_0_3 = digits1_1[0];
	  digits_2[0] = digits1_0_3;
	  final int digits1_1_6 = digits1_1[1];
	  digits_2[1] = digits1_1_6;
	  final int digits1_2_9 = digits1_1[2];
	  digits_2[2] = digits1_2_9;
	  final int digits1_3_12 = digits1_1[3];
	  digits_2[3] = digits1_3_12;
	  final int[] digits_22 = new int[4];
	  digits_22[0] = digits1_0_3;
	  digits_22[1] = digits1_1_6;
	  digits_22[2] = digits1_2_9;
	  digits_22[3] = digits1_3_12;
	  if (digits1_0_3 == 0) {
	    throw new java.lang.Exception();}
	  if (digits1_0_3 == 1) {
	    if (digits1_1_6 == 0
	    ||  digits1_1_6 == 1
	    ||  digits1_1_6 != 2
	    ||  digits1_2_9 == 0
	    ||  digits1_2_9 != 1
	    ||  digits1_3_12 != 0) {
	      throw new java.lang.Exception();}
	    java.lang.System.out.println("1210") /*virtual*/;}
	  else {
	    if (digits1_0_3 != 2
	    ||  digits1_1_6 != 0
	    ||  digits1_2_9 == 0
	    ||  digits1_2_9 == 1
	    ||  digits1_2_9 != 2
	    ||  digits1_3_12 != 0) {
	      throw new java.lang.Exception();}
	    java.lang.System.out.println("2020") /*virtual*/;}
	  return;
	}
//--------------------------------   6 sec - JScp version 0.1.22

 

nofDigits = 5 (одно решение) 

 
public static void checkAndPrint (final int[] digits1_1)
	  throws java.lang.Exception
	{
	  final int[] digits_2 = new int[5];
	  final int digits1_0_3 = digits1_1[0];
	  digits_2[0] = digits1_0_3;
	  final int digits1_1_6 = digits1_1[1];
	  digits_2[1] = digits1_1_6;
	  final int digits1_2_9 = digits1_1[2];
	  digits_2[2] = digits1_2_9;
	  final int digits1_3_12 = digits1_1[3];
	  digits_2[3] = digits1_3_12;
	  final int digits1_4_15 = digits1_1[4];
	  digits_2[4] = digits1_4_15;
	  final int[] digits_26 = new int[5];
	  digits_26[0] = digits1_0_3;
	  digits_26[1] = digits1_1_6;
	  digits_26[2] = digits1_2_9;
	  digits_26[3] = digits1_3_12;
	  digits_26[4] = digits1_4_15;
	  if (digits1_0_3 == 0
	  ||  digits1_0_3 == 1
	  ||  digits1_0_3 != 2
	  ||  digits1_1_6 == 0
	  ||  digits1_1_6 != 1
	  ||  digits1_2_9 == 0
	  ||  digits1_2_9 == 1
	  ||  digits1_2_9 != 2
	  ||  digits1_3_12 != 0
	  ||  digits1_4_15 != 0) {
	    throw new java.lang.Exception();}
	  java.lang.System.out.println("21200") /*virtual*/;
	  return;
	}
//------------------------------- 135 sec - JScp version 0.1.22

Время суперкомпиляции резко увеличивается, поэтому на этом эксперименты были прекращены.

 

Схема математического решения

Пусть a0 , a1 , ... , an - цифры искомого n+1-значного числа. Подсчет количества цифр (=n+1) различными способами (от перестановки мест слагаемых сумма не меняется) дает два соотношения

a0 + a1 + ... + an = n+1

0*a0 + 1*a1 + 2*a2 + ... + n*an = n+1

Т.е., сумма цифр равняется значности числа, и сумма с коэффициентами тоже равняется значности числа.

Далее идет какой-то перебор возникающих вариантов с учетом большого количества нулей.