標籤:

7個10以下數(0-9)相加(可重複),和的個位數為0.問每個數字(0-9)出現的概率是多少?


沒描述好,應該是想問:

設x1, x2, ..., x7是7個獨立同分布的隨機變數,取值為0-9的整數,概率各為1/10,求 P(x_1| x_1 + x_2 + ... +x_7 equiv 0 pmod {10}) 的條件概率分布

因為7個變數是對稱的,所以任意一個的概率分布都是相同的。

解法也沒什麼意思,因為不管是前6個還是前7個的和對10取模仍然是0-9的均勻分布,所以說穿了幾個相加都沒什麼區別,每個數位上出現的數字仍然是均勻分布。

另一種理解是7個數的集合中是否包含某個數,解法有些不同。但是也不難:

基本方法是容斥原理,我們先計算至少有一位出現的情況,這當中包含了至少出現兩次的情況,而且其中每個都被算了兩次,所以減掉一次;但是,至少出現三次的情況又被減沒了,要再加回來;這麼一算,出現四次的又多算了一次,又要減掉……這個鬧心的公式就叫做容斥原理公式。注意到k個數相加模10結果為m的情況都剛好有10^(k-1)種,唯獨對於出現了7次的情況來說,由於7和10是互質的,只有7個0才有可能,所以最終,0出現的情況多了一種(也就是7個0)

非0數字的出現情況:

C_7^1 10^5 - C_7^210^4+C_7^310^3-C_7^410^2+C_7^5 10 - C_7^6

= 700000 - 210000 + 35000 - 3500 + 210 - 7

=521703

0出現的情況:

C_7^1 10^5 - C_7^210^4+C_7^310^3-C_7^410^2+C_7^5 10 - C_7^6+C_7^7

=521704

對於n個數相加和為m的情況也是類似的,如果n個某個數字相加的和取模恰好為m,則出現情況會多1,計算公式還是上面那個。

當然更簡便的計算方式也是有的,考慮到:

(10-1)^k = C_k^0 10^k - C_k^1 10^{k-1} + C_k^2 10^{k-2} ... + (-1)^kC_k^k

= 10^k + (-1)^k - 10(C_k^1 10^{k-2} - C_k^2 10^{k-3} + ... + (-1)^{k-2}C_k^{k-1})

所以要求的結果就是

frac{10^k - 9^k + (-1)^k}{10}

在k個該數字相加等於需要的m時,結果是

frac{10^k - 9^k + (-1)^k}{10} + 1

驗算一下:

frac{10^7 - 9^7 + (-1)^7}{10} = 521703


開Excel寫VBA窮舉之,也就一千萬個組合。

自己窮聚了一下,0比其他數字多了一丁點,幾乎所有都是5.2%多一點。我把概率理解為,一千萬個組合裡面,出現含有數字x的組合的數量在全體中的比值,稱為x出現的概率。7個1也算1個1,只算「出現」。


為什麼我算出來的概率是52.1703%

#include &
#include &
using namespace std;

int total = 0;
int sub[10];

int counts[10];

void dfs(int level, int sum) {
if (level == 7) {
if (sum % 10 == 0) {
total++;
for (int i = 0; i &< 10; i++) { if (counts[i]) { sub[i]++; } } } return; } for (int i = 0; i &< 10; i++) { counts[i]++; dfs(level + 1, sum + i); counts[i]--; } } int main() { memset(counts, 0, sizeof(counts)); memset(sub, 0, sizeof(sub)); dfs(0, 0); cout &<&< total &<&< endl; for (int i = 0; i &< 10; i++) { cout &<&< i &<&< ": " &<&< sub[i] &<&< endl; } }


用sql嘗試了一下……雖然很醜……

建了一個臨時表, 十行,分別是1-0 。 我很好奇為啥比樓上一個大佬算的少1……

select sum(decode(instr(v_char,1),0,0,1)) as s_1,
sum(decode(instr(v_char,2),0,0,1)) as s_2,
sum(decode(instr(v_char,3),0,0,1)) as s_3,
sum(decode(instr(v_char,4),0,0,1)) as s_4,
sum(decode(instr(v_char,5),0,0,1)) as s_5,
sum(decode(instr(v_char,6),0,0,1)) as s_6,
sum(decode(instr(v_char,7),0,0,1)) as s_7,
sum(decode(instr(v_char,8),0,0,1)) as s_8,
sum(decode(instr(v_char,9),0,0,1)) as s_9,
sum(decode(instr(v_char,0),0,0,1)) as s_0
from (select to_char(t_1.t1 + t_1.t1 + t_2.t1 + t_3.t1 + t_4.t1 + t_5.t1 +
t_6.t1 + t_7.t1) as v_sum,
t_1.t1 || t_1.t1 || t_2.t1 || t_3.t1 || t_4.t1 || t_5.t1 || t_6.t1 || t_7.t1 as v_char
from t_1 t_1, t_1 t_2, t_1 t_3, t_1 t_4, t_1 t_5, t_1 t_6, t_1 t_7)
where substr(v_sum, length(v_sum), 1) = 0

S_1 S_2 S_3 S_4 S_5 S_6 S_7 S_8 S_9 S_0
1 521702 521702 521702 521702 521703 521702 521702 521702 521702 521703


結果:52.17%

我理解的題目是:以9為例,所有和的個位數為0的結果中,某一組中出現過9則這一組即為一次。

代碼如下:

#include &
#include &
#include &

using namespace std;

void dfs(vector& ret, vector& tmp, int sum, int n, int count)
{
if(n == 7 sum % 10 == 0)
{
count++;
for(int i = 0; i &< 10; i++) if(tmp[i] != 0) ret[i]++; return; } else if(n == 7) return; for(int i = 0; i &< 10; i++) { tmp[i]++; sum += i; dfs(ret, tmp, sum, n + 1, count); sum -= i; tmp[i]--; } } int main() { vector& ret(10, 0);
vector& tmp(10, 0);
int sum = 0;
int count = 0;

dfs(ret, tmp, sum, 0, count);

printf("總計: %d
", count);

for(int i = 0; i &< 10; i++) { printf("%d出現的次數:%d ", i, ret[i]); } return 0; }

PS:這道題的結果如果各個數字概率和為1的很明顯是錯的。出現數字1的組合概率和不出現數字1的組合概率之和才是1。舉一個簡單的例子:ab, ac, bc問字元串中出現b的概率是多少?2/3。而且字元串中出現a,b,c的概率分別都是2/3。


&>&>&> a = range(10)
&>&>&> b = itertools.product(a, repeat=7)
&>&>&> c = filter(lambda x: sum(x) % 10 == 0, b)
&>&>&> d = itertools.chain.from_iterable(c)
&>&>&> e = Counter(list(d))
&>&>&> e
Counter({0: 700000, 1: 700000, 9: 700000, 2: 700000, 8: 700000, 3: 700000, 7: 700000, 4: 700000, 6: 700000, 5: 700000})


請問,為什麼我的答案和輪子哥不一樣。。?

………………昏割線…………

評論區提醒了我為什麼結果不一樣,7個數字不同排列只算一組,所以我的錯了,50%多的才是正解。


// 10個數字可以重複,但是應該相互之間是沒有順序的。如7個0的情況,不應當算作0出現了7!次。
// 因此要避免出現重複。故我在遞歸中加入了大小順序的限制,使在統計時,方便快速排除重複。
// 最後出現的結果共有1144個組合,0-9出現的次數分別是
// 504,497,504,497,504,497,504,497,504,497
// 也即,0-9根據其是偶數或奇數,出現的概率分別是,44.05%和43.44%

var arr = [0,0,0,0,0,0,0,0,0,0];
var index = [0,0,0,0,0,0,0];
var count = 0;

function step(indent, next, arr, index){
if(indent === 7){
if(index.reduce((a, b) =&> a + b)%10 === 0){
count++;
console.log(index);
var tem = 11;
for(var j = 0; j&< 7;j++){ if(index[j] &< tem){ arr[index[j]]++; tem = index[j]; } } } return; } for(var i=0; i &<= next; i++){ index[indent] = i; step(indent+1, i, arr, index); } } step(0, 9, arr,index); console.log(count+": "+arr);



審題失誤,看成和為0的概率了

已知和為0的條件下求每個數字的概率在枚舉之後加個判斷就好

還是各自10%


大家答案不一樣的原因是0出現的概率和其他數字本來就不一樣,因為7和10是互質的,其他結果可以實現11對應。

如果考慮0出現的次數,F(i,j)表示前i個個和mod10為j且不出現0的可能數。我們要求的是S(i)=前i個和mod為0且不出現0的可能數=F(i,0)

因為

F(i,j)=求和(對於k不等於j)F(i-1,k)

所以S(i)=求和(k=1,...,9)F(i-1,k)

=9F(i-2,0)+8*求和(k=1,..,9)F(i-2,k)

=8S(i-1)+9S(i-2)

S(1)=0,S(2)=9

所以S(k)=9^k/10+9*(-1)^k/10

最後0出現的個數就是10^6-S(7)=521704

如果考慮1或者別的數字出現的次數,同上面的符號不難求出F(7,1)=S(7)+1,也就是七個數和mod10為1不出現0的值,不難發現這個可以和七個數和mod10為0不出現k(k=1,...9)的集合可以一一對應所以最終結果就會少1,也就是521703


這個是微信紅包賭博套路,大家不要幫忙算了。

發自於我的蘋果


每個數字出現概率都是0.7

end0Count = 1000000

num 0 times=700000. rate=0.700000
num 1 times=700000. rate=0.700000
num 2 times=700000. rate=0.700000
num 3 times=700000. rate=0.700000
num 4 times=700000. rate=0.700000
num 5 times=700000. rate=0.700000
num 6 times=700000. rate=0.700000
num 7 times=700000. rate=0.700000
num 8 times=700000. rate=0.700000
num 9 times=700000. rate=0.700000

// 各位數相加以0結尾
bool bitSumEnd0(int num) {

int sum = 0;

while (num &> 0) {
sum += num % 10;
num /= 10;
}

return sum % 10 == 0;
}
// 7個個位數(可重複)相加之和的個位是0,每個數字出現的概率
void calNum()
{
int numTimesArray[10] = {0};

int end0Count = 0;
for (int i=0; i&<9999999; i++) { if (bitSumEnd0(i)) { end0Count++; int num = i; int bitCount = 0; while (num &> 0) {
bitCount++;
numTimesArray[num % 10]++;
num /= 10;
}

if (bitCount &< 7) { numTimesArray[0] += (7-bitCount); } } } printf(" end0Count = %d ", end0Count); for (int i=0; i&<10; i++) { printf("num %d times=%d. rate=%lf ", i, numTimesArray[i], numTimesArray[i] * 1.0 / end0Count); } }


雖然不清楚提問的人究竟問啥.. 但按照題目的理解過程是:

在求和之後個位為0 的7個數字構成的一系列排列中,(0-9)各自出現的概率(因提問是出現的概率,所以認為只要在排列中出現,則無論在該排列中有多少個,均視作出現)

即解題過程為:

  1. 求得所有 求和之後個位為0 的7個數字構成的一系列排列
  2. 統計(0-9)在這一系列排列中出現過的組數佔全組合數量的比例

所以...這道繞口的題目,個人解答如下。。

如果大家認同 2個數的結果的話。。那7個數的結果就是醬紫

PS:這是排列..如果是組合的話 就-。-換種演算法吧


首先這個題目題乾的表意就不是很明確吧,每個數字出現的概率指的是什麼?我覺得可以有兩種理解:設七個數為a,b,c,d,e,f,g,和為s且s的個位為0,既可以是指(0-9)這九個數字在所有滿足條件的s中出現的次數,也可以指在所有(a,b,c,d,e,f,g)數組中出現的概率吧。

我個人開始的理解是前一種,寫了一個python程序算了下:

結果是0出現1000000次,1出現8001次,2出現174195次,3出現504315次,4出現286860 次,5出現26544次,6出現84次,7,8,9不出現。

python剛學兩天,代碼比較簡陋,見諒


第五次讀題,讀懂了


先上結論:

加數的數字出現頻率的統計結果:

允許重複組合的話,所有數字出現的頻率都是10%,這是因為不管前面的組合為何,總有且只有1個最後的數字,使得結果的個位數為0。

而不允許重複組合的話,結果如下:

加數中出現的數字的頻率(不允許重複組合)

結果的數字出現頻率的統計結果:

結果中出現的數字的頻率(允許重複組合)

結果中出現的數字的頻率(不允許重複組合)

9*7=63,也就是說最大的數字也就63而已,所以7、8、9都不會出現在十位上,出現次數就比其他數字少。

同樣地,由於63沒有達到百位數,十位數不會是0,所以假如不要求個位數為0,0的出現次數就會比別的數字少。但如果要求個位數為0,每個合法組合都會有至少1個0,0的出現次數就會被別的數字多。

由於X個數相加的結果服從正態分布,0~63之間的峰值是31和32,所以十位數是2和3的幾率最高。

故,結果如上圖所示。

三份代碼加起來太長了,有需要的人請私信吧。下面只有統計加數,不允許重複組合的代碼:

修改第四行的「#define SIZE 7」最後面的數字就可以計算不同的加數了。比如我想計算3個加數的和的結果,就將第三行改成「#define SIZE 3」

#include & /* cout */
#include & /* vector */
#include & /* array */
#define SIZE 7

using namespace std;

void printResult(int data[10], int total, int totalNumber)
{
cout &<&< "一共有" &<&< total &<&< "個組合,使用了 " &<&< totalNumber &<&< "個數字" &<&< endl; for (int i = 0; i &< 10; i++) cout &<&< i &<&< " 一共出現 " &<&< data[i] &<&< " 次,佔總數 " &<&< (float)data[i] / (float)totalNumber * 100 &<&< "%" &<&< endl; } bool noSameComb(vector&&> combinationSet, array& numbersFreq)
{
bool sameFreq = true;
for (int i = 0; i &< combinationSet.size(); i++) { sameFreq = true; for (int j = 0; j &< 10; j++) { if (numbersFreq[j] != combinationSet[i][j]) { sameFreq = false; break; } } if (sameFreq) return false; } return true; } void calculate(int numbers[SIZE], int counter[10], vector&&> combinationSet, int totalCount, int currPosition)
{
if (currPosition == SIZE - 1)
{
int result = 0;
array& freq = { 0 };

for (int i = 0; i &< SIZE - 1; i++) result += numbers[i]; //不需要實際計算最後一個數字 //只要不斷給之前的結果+1就相當於歷遍最後一個數字的所有可能了 for (int i = 0; i &< 10; i++) { if (result % 10 == 0)//如果個位為0 { //計算每個數字的出現次數 for (int i = 0; i &< SIZE; i++) freq[numbers[i]]++; //檢查該數字組合有沒有曾經出現過 if (noSameComb(combinationSet, freq)) { totalCount++; combinationSet.push_back(freq); for (int i = 0; i &< SIZE; i++) counter[numbers[i]]++; } break;//不管前面結果如何,最後一個數字有且只有一個可能出現個位為0 } result++; numbers[currPosition]++; } } else { while (numbers[currPosition]&< 10) { //將當前位置之後的數字都初始化,從零開始歷遍 numbers[currPosition + 1] = 0; calculate(numbers, counter, combinationSet, totalCount, currPosition + 1); numbers[currPosition]++; } } } int main() { int addElement[SIZE] = { 0 }; int counter[10] = { 0 }; int totalCount = 0; vector&&> combinationSet;

calculate(addElement, counter, combinationSet, totalCount, 0);
printResult(counter, totalCount, totalCount*SIZE);

return 0;
}


不負責任地答一發。

用C++窮舉了一遍。

7個10以下數(0-9)相加(可重複)的結果是10000000

和的個位數為0結果是1000000

在和的個位數為0的結果中,每個數字出現的次數都是700000

至於概率,有待對問題進一步理解。。我覺得可能是700000/1000000

演算法大概是for 0-9 7層嵌套 然後相加 if對10求余為0 switch每個數 代碼太醜陋,不貼了e

分割

這種方法應該是錯的,重複計算了。


用python寫了小段代碼,計算了一千萬次,每個數出現的概率越來越趨近於10%,結果如下:(手機複製,大家不要吐槽我的縮進)


Bayes Law.


不太懂,我在想是不是 @vczh 簡單的程序就能解決

感覺很多人審題錯誤了。題主問的是在和的個位數為0的情況下,0-9這10個數各自出現的概率吧


是不是應該先說實名反對輪子哥…

0出現588889次,其他的都是700000次


推薦閱讀:

一年3起大型空難的概率是多少?
陰陽師姑獲鳥"金鸞鶴羽"皮膚,世界公告是否有造假的嫌疑?
為什麼有人會經常中獎,或者為什麼有人運氣一直很差?
如此下去,哪個國家男人比例最多?

TAG:數學 | 概率 |