n个色子的和的概率

来源:互联网 发布:360比价软件 编辑:程序博客网 时间:2024/05/14 10:17

这个题目来自剑指offerhttp://zhedahht.blog.163.com/blog/static/254111742009101524946359/

n个骰子的点数和的最小值为n,最大值为6n。因此,一个直观的思路就是定义一个长度为6n-n的数组,和为S的点数出现的次数保存到数组第S-n个元素里。另外,我们还知道n个骰子的所有点数的排列数6^n。一旦我们统计出每一点数出现的次数之后,因此只要把每一点数出现的次数除以n^6,就得到了对应的概率。

之前编写过全排列的程序,

/* Note:Your choice is C IDE */#include "stdio.h"#include<malloc.h>#include<math.h>int sum_arr_n(int arr[],int n){int i;int sum=0;for(i=0;i<n;i++)sum+=arr[i];return sum;}void QuanPaiLei(int n,int m){//这里N为6,m为色子数int count=0;int arr[100];int i,j=0;int total=pow(n,m);int *arr_sum=(int *)malloc((n*m+1)*sizeof(int));if(NULL==arr_sum)return;memset(arr_sum,0,(n*m+1)*sizeof(int));i=0;arr[0]=1;while(1){if(i==m-1){arr_sum[sum_arr_n(arr,m)]++;count++;}if(i<m-1){i++;arr[i]=1;////每个都要从1开始continue;}while(arr[i]==n)i--;if(i>=0)arr[i]++;elsebreak;}for(i=1;i<=n*m;i++){if(arr_sum[i]!=0)printf("%d:%d/%d\n",i,arr_sum[i],total);//printf("%d:%.2f\n",i,arr_sum[i]*1.0/total);}free(arr_sum);}void main(){    QuanPaiLei(6,4);//即4个色子的情况:}
4:1/12965:4/12966:10/12967:20/12968:35/12969:56/129610:80/129611:104/129612:125/129613:140/129614:146/129615:140/129616:125/129617:104/129618:80/129619:56/129620:35/129621:20/129622:10/129623:4/129624:1/1296             Press any key to continue

2个色子的情况

2:1/363:2/364:3/365:4/366:5/367:6/368:5/369:4/3610:3/3611:2/3612:1/36

________________________________________________________________________________________________________

其他解法1.递归的方式

不要求输出每种排列方式。n个色子,则组合的和结果在n-6n之间,从而共有5n+1种和。假设要得到的和为sum

每个色子在1-6之间,若第i(1-n)个骰子点数为m,则之后的点和等于sum-m.若sum-m==0同时i==n,则说明是一个正确的组合方式。

#include<stdio.h>#include<stdlib.h>#include<math.h>void Get_sum_count(int n,int sum,int *count)//n个骰子之和等于sum的可能组合数,count是记录组合数目{int i;    if(sum < 0)         return;    if(0==n && sum!= 0)       return;    if(n==0 && sum==0)//找到一组可行解,count++    {       (*count)++;    }    for(i=1;i<7;i++)//以下为递归过程    {       Get_sum_count(n-1,sum-i,count);//如果倒数第n个骰子是点数是i,       //那么剩下的n-i个骰子的点数之和要等于sum-i,才能得出一个有效解       //每次递归sum减少。    }     }int main(){   int count = 0;//n个骰子点数之和为sum的组合数目   int n = 0,i,j;   int sum = 0;   int total;//=pow()   int *arr_sum=NULL;//用于指向和的数组   do{   printf("输入骰子数\n");        scanf("%d",&n);         }while(n<1);    arr_sum= (int*)malloc((n*5+1)*sizeof(int));//n个骰子点数和只有5*n+1种。在n,到6*n之间   memset(arr_sum,0,(n*5+1)*sizeof(int));     for(i = n;i < 6*n+1;i++)//i为n个骰子的和   {             Get_sum_count(n,i,&count);      sum += count;  arr_sum[i-n] = count;  count = 0;   }   total=pow(6,n);   for(j=0;j<n*5+1;j++)   {      printf("%d:%d/%d\n",j+n,arr_sum[j],total);   }   free(arr_sum);    return 0 ;}

输入骰子数 33:1/2164:3/2165:6/2166:10/2167:15/2168:21/2169:25/21610:27/21611:27/21612:25/21613:21/21614:15/21615:10/21616:6/21617:3/21618:1/216             Press any key to continue

转载请标明出处:http://blog.csdn.net/lin200753/article/details/27825751

0 0