¿Cómo puedo generar 8 números (aleatorios) que deberían oscilar entre 0 y 80 y la suma de esos 8 números generados debería ser 80.?

Aquí hay dos métodos para generar 8 números reales positivos que suman 80 que se distribuyen uniformemente en el simplex [matemática] x_1 + x_2 +… + x_8 = 80, x_i \ ge 0. [/ matemática] Ambos métodos se mencionan en el usuario de Wikipedia: Skinnerd / Simplex Point Picking.

Método 1 : generar 7 reales aleatorios uniformes en [0,80]. Ordénelos para obtener [matemática] 0 \ le y_1 \ le y_2 \ le… \ le y_7 \ le 80 [/ matemática]. Luego deje que [math] x_1 = y_1, x_2 = y_2-y_1, [/ math] [math] x_3 = y_3-y_2,… x_7 = y_7-y_6, x_8 = 80-y_7. [/ Math] La colección [math] (x_1, x_2, …, x_8) [/ math] se distribuye uniformemente en el simplex.

Método 2 : Genere 8 variables aleatorias que sean uniformes en [0,1], [matemáticas] u_1, …, u_8 [/ matemáticas]. Entonces las variables aleatorias [math] z_i = – \ log u_i [/ ​​math] se distribuyen exponencialmente con el parámetro 1. Sea la suma de estas S. Entonces, [math] x_i = 80 z_i / S [/ math]. La colección se distribuye uniformemente en el simplex.

Hay bastantes trucos útiles como este para el muestreo de distribuciones. Estos no son fáciles de resolver desde los primeros principios, pero puede encontrar los algoritmos buscando cosas como “muestra de esfera” (en caso de que quiera hacer eso a continuación).

Ok, entonces preparé una solución. Quizás no sea el mejor, pero supongo que funcionará.
Lo que estoy haciendo es

  1. Generando un número aleatorio del 0 al total (inicialmente establecido en 80)
  2. Restando ese número del total, almacenándolo. Y aumentando un contador para ese número.

Por ejemplo, si obtengo el número 2. Estoy aumentando el contador en la matriz de números para 2 por 1
3. Repita los pasos 1 y 2 hasta obtener 8 números (por ahora puede haber repeticiones)
4. Ahora, para eliminar los duplicados, reviso cada número y compruebo si su contador es mayor que 1. Si es así, reviso mi matriz de números hasta llegar a un número cuyo contador es 0 y establezco mi número en ese número.
5. Finalmente, tomo la suma de todos los números y si es mayor que 80 resto la diferencia del último número. (Aquí solo cuento con el hecho de que mi último número será lo suficientemente grande como para que no se vuelva negativo en la resta)

Aquí está mi código:

  #include 
 usando el espacio de nombres estándar;
 número int [81];
 int main ()
 {
     int n = 7, x, total = 80, suma = 0, bandera = 0;
     int a [8];
     srand (tiempo (NULL));
     mientras que (n> = 0)
     {
            x = rand ()% total;
            total = total-x;
            a [n] = x;
            número [x] ++;
            norte--;
     }
     para (int i = 0; i <8; i ++)
     {
             if (número [a [i]]> 1)
             {
                 para (int j = a [i]; verdadero; j ++)
                 {
                         if (número [j] == 0)
                         {
                                         a [i] = j;
                                         número [j] ++;
                                         rotura;
                         }
                 }
             }
             suma + = a [i];
     }               
     si (suma> 80)
     a [7] - = suma-80;
     suma = 0;
     para (int i = 0; i <8; i ++)
     {
             cout << a [i] << "";
             suma + = a [i];
     }
    
     cout << "\ nSUM =" << sum << endl;
     sistema ("pausa");
     devuelve 0;
 }

Pero probablemente hay un mejor método. Espero que esto sea satisfactorio.
EDITAR:

en caso de que se permita la repetición, puedo eliminar la parte de ajuste y el código ahora se convierte

  #include 
 usando el espacio de nombres estándar;
 número int [81];
 int main ()
 {
     int n = 7, x, total = 80, suma = 0, bandera = 0;
     int a [8];
     srand (tiempo (NULL));
     mientras que (n> = 0)
     {
            x = rand ()% total;
            total = total-x;
            suma + = x;
            a [n] = x;
            número [x] ++;
            norte--;
     }
     if (sum <80) // para asegurar que sum es 80 ya que los números aleatorios pueden tener su suma <80
     a [0] + = suma de 80;
     suma = 0;
     para (int i = 0; i <8; i ++)
     {
             cout << a [i] << "";
             suma + = a [i];
     }
    
     cout << "\ nSUM =" << sum << endl;
     sistema ("pausa");
     devuelve 0;
 }

Matemáticamente se genera un número aleatorio de esta manera: http://mathworld.wolfram.com/Ran

Sin embargo, no sé cómo encontrar números cuya suma sea igual a X sin probar uno por uno.