7個10以下數(0-9)相加(可重複),和的個位數為0.問每個數字(0-9)出現的概率是多少?
沒描述好,應該是想問:
設x1, x2, ..., x7是7個獨立同分布的隨機變數,取值為0-9的整數,概率各為1/10,求 的條件概率分布
因為7個變數是對稱的,所以任意一個的概率分布都是相同的。
解法也沒什麼意思,因為不管是前6個還是前7個的和對10取模仍然是0-9的均勻分布,所以說穿了幾個相加都沒什麼區別,每個數位上出現的數字仍然是均勻分布。
另一種理解是7個數的集合中是否包含某個數,解法有些不同。但是也不難:
基本方法是容斥原理,我們先計算至少有一位出現的情況,這當中包含了至少出現兩次的情況,而且其中每個都被算了兩次,所以減掉一次;但是,至少出現三次的情況又被減沒了,要再加回來;這麼一算,出現四次的又多算了一次,又要減掉……這個鬧心的公式就叫做容斥原理公式。注意到k個數相加模10結果為m的情況都剛好有10^(k-1)種,唯獨對於出現了7次的情況來說,由於7和10是互質的,只有7個0才有可能,所以最終,0出現的情況多了一種(也就是7個0)
非0數字的出現情況:
0出現的情況:
對於n個數相加和為m的情況也是類似的,如果n個某個數字相加的和取模恰好為m,則出現情況會多1,計算公式還是上面那個。
當然更簡便的計算方式也是有的,考慮到:
所以要求的結果就是
在k個該數字相加等於需要的m時,結果是
驗算一下:
開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&
{
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&
vector&
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)各自出現的概率(因提問是出現的概率,所以認為只要在排列中出現,則無論在該排列中有多少個,均視作出現)
即解題過程為:
- 求得所有 求和之後個位為0 的7個數字構成的一系列排列
- 統計(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 &
#include &
#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&
{
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&
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起大型空難的概率是多少?
※陰陽師姑獲鳥"金鸞鶴羽"皮膚,世界公告是否有造假的嫌疑?
※為什麼有人會經常中獎,或者為什麼有人運氣一直很差?
※如此下去,哪個國家男人比例最多?