微軟面試題之數字謎題 (轉)
設有兩個自然數m,n,2〈=m<=99。 S先生知道這兩數的和s,P先生知道這兩數的積p。他們兩人進行了如下的對話:
S:我知道你不知道這兩個數是什麼,但我也不知道。
P:現在我知道這兩個數了。
S:現在我也知道這兩個數了。
由這些條件,試確定m,n。
因為S知道兩數之和,卻由此推斷P不知道兩個數,所以說兩數之和s一定不能拆分成兩個素數的和,即m,n不可能都是素數,且m,n中不會有大於50的素數,否則的話m*n可以唯一分解,P知道了m,n的積就一定可以知道m,n了。
P從S的言語中能夠判斷出的資訊是:
1。m,n不會全是素數;
2。m,n中不會有大於50的素數;
3。m,n之和不能拆成兩個素數的和;
4。因為S自己也不知道這兩個數是什麼,所以這兩個數的和一定小於99+98,否則S就可以知道這兩個數是什麼了。
滿足以上條件的 s=m+n有以下的可能:
11
17
23
27
29
35
37
41
47
196
然後P根據自己掌握的p=m*n立即算出m,n,這說明p=m*n是具有以下性質的特殊數字:
根據這個特殊的p,當s取上面的那些值的時候,只有一種s的取值使得方程
m+n=s,
m*n=p
在[2,99]內有唯一的整數解。
根據這個性質計算出的p有以下的情況(不妨設m<=n):
p = 18, s= 11, m = 2, n = 9
p = 24, s= 11, m = 3, n = 8
p = 28, s= 11, m = 4, n = 7
p = 50, s= 27, m = 2, n = 25
p = 52, s= 17, m = 4, n = 13
p = 54, s= 29, m = 2, n = 27
p = 76, s= 23, m = 4, n = 19
p = 92, s= 27, m = 4, n = 23
p = 96, s= 35, m = 3, n = 32
p = 100, s= 29, m = 4, n = 25
p = 110, s= 27, m = 5, n = 22
p = 112, s= 23, m = 7, n = 16
p = 114, s= 41, m = 3, n = 38
p = 124, s= 35, m = 4, n = 31
p = 130, s= 23, m = 10, n = 13
p = 138, s= 29, m = 6, n = 23
p = 140, s= 27, m = 7, n = 20
p = 148, s= 41, m = 4, n = 37
p = 150, s= 35, m = 5, n = 30
p = 152, s= 27, m = 8, n = 19
p = 154, s= 29, m = 7, n = 22
p = 160, s= 37, m = 5, n = 32
p = 162, s= 27, m = 9, n = 18
p = 168, s= 29, m = 8, n = 21
p = 170, s= 27, m = 10, n = 17
p = 172, s= 47, m = 4, n = 43
p = 174, s= 35, m = 6, n = 29
p = 176, s= 27, m = 11, n = 16
p = 182, s= 27, m = 13, n = 14
p = 186, s= 37, m = 6, n = 31
p = 190, s= 29, m = 10, n = 19
p = 196, s= 35, m = 7, n = 28
p = 198, s= 29, m = 11, n = 18
p = 204, s= 29, m = 12, n = 17
p = 208, s= 29, m = 13, n = 16
p = 216, s= 35, m = 8, n = 27
p = 232, s= 37, m = 8, n = 29
p = 234, s= 35, m = 9, n = 26
p = 238, s= 41, m = 7, n = 34
p = 246, s= 47, m = 6, n = 41
p = 250, s= 35, m = 10, n = 25
p = 252, s= 37, m = 9, n = 28
p = 270, s= 37, m = 10, n = 27
p = 276, s= 35, m = 12, n = 23
p = 280, s= 47, m = 7, n = 40
p = 288, s= 41, m = 9, n = 32
p = 294, s= 35, m = 14, n = 21
p = 304, s= 35, m = 16, n = 19
p = 306, s= 35, m = 17, n = 18
p = 310, s= 41, m = 10, n = 31
p = 322, s= 37, m = 14, n = 23
p = 336, s= 37, m = 16, n = 21
p = 340, s= 37, m = 17, n = 20
p = 348, s= 41, m = 12, n = 29
p = 364, s= 41, m = 13, n = 28
p = 370, s= 47, m = 10, n = 37
p = 378, s= 41, m = 14, n = 27
p = 390, s= 41, m = 15, n = 26
p = 396, s= 47, m = 11, n = 36
p = 400, s= 41, m = 16, n = 25
p = 408, s= 41, m = 17, n = 24
p = 414, s= 41, m = 18, n = 23
p = 418, s= 41, m = 19, n = 22
p = 442, s= 47, m = 13, n = 34
p = 462, s= 47, m = 14, n = 33
p = 480, s= 47, m = 15, n = 32
p = 496, s= 47, m = 16, n = 31
p = 510, s= 47, m = 17, n = 30
p = 522, s= 47, m = 18, n = 29
p = 532, s= 47, m = 19, n = 28
p = 540, s= 47, m = 20, n = 27
p = 546, s= 47, m = 21, n = 26
p = 550, s= 47, m = 22, n = 25
p = 552, s= 47, m = 23, n = 24
p = 9604, s= 196, m = 98, n = 98
最後P說出自己已經知道m,n以後,S也說自己知道了m,n,這說明S根據自己手中的兩數之和可以推斷出唯一的m,n來。
因此還要去除上面的情況中重複用到s的情況,得到下面的情況:
p = 52, s = 17, m = 4, n = 13
p = 9604, s = 196, m = 98, n = 98
如果規定了m<>n,則最後的解答就是
m=4 , n=13
下面是:
#include
#include
#include
const int MAX_N = 99;
const char* OUTPUT_FILE = "result.txt";
int s[MAX_N*2];
int p[MAX_N*MAX_N];
int prim[MAX_N];
int primCounter =0;
ofstream fout( OUTPUT_FILE );
// 計算素數
void calPrim()
{
bool used[MAX_N];
int i, p=2;
bool found = true;
prim[primCounter++] = 2;
memset( used, false, sizeof( used ) );
while( found ) {
for( i = p; i < MAX_N; i++ )
if( i % p == 0 )
used[i] = true;
found = false;
for( i = p; i < MAX_N; i++ )
if( ! used[i] ) {
p = i;
prim[primCounter++] = p;
found = true;
break;
}
}
}
// 根據條件1過濾
void useCon_1()
{
int i,j;
memset(s, 0, sizeof(s));
for( i = 0; i < 4; i++ ) s[i] =-1;
calPrim();
// S可以肯定P不知道這兩個數是什麼
for( i = 0; i < primCounter; i++ )
for( j = i; j < primCounter; j++ ) {
if( prim[i] + prim[j] < MAX_N * 2 )
s[ prim[i] + prim[j] ] = -1;
}
for( i = 0; i < primCounter; i++ )
if( prim[i] > MAX_N / 2 ) break;
for( i--; i < primCounter; i++ )
for( j = 2; j < MAX_N; j++ )
s[ prim[i] + j ] = -1;
// 因為S自己也不知道這兩個數是什麼
for( i = 98 + 99; i < MAX_N + MAX_N; i++ )
s[i] = -1;
fout << "滿足S第一句話的兩數之和" << endl;
for( i = 0; i < MAX_N * 2; i++ )
if( s[i] == 0 )
fout << i << endl;
}
// 根據條件2過濾
void useCon_2()
{
int i, m, n;
memset( p, 0, sizeof( p ) );
for( m = 2; m < MAX_N; m++ )
for( n = 2; n < MAX_N; n++ ) {
if( s[m+n] >= 0 ) {
p[m*n]++;
}
}
fout << "滿足P第一句話的兩數之積:" << endl;
for( i = 0; i < MAX_N * MAX_N; i++ )
if( p[i] == 1 || p[i] == 2 ) {
for( m = 2; m < MAX_N; m++ )
for( n = m; n < MAX_N; n++ )
if( m * n == i && s[m + n] >= 0 ) {
fout << "p = " << i
<< ", s= " << m + n
<< ", m = " << m
<< ", n = " << n << endl;
s[m+n]++;
}
}
}
void useCon_3()
{
int i, m, n;
fout << "滿足S第二句話的結果:" << endl;
for( i = 0; i < MAX_N * MAX_N; i++ )
if( p[i] == 1 || p[i] == 2 ) {
for( m = 2; m < MAX_N; m++ )
for( n = m; n < MAX_N; n++ )
if( m * n == i && s[m + n] == 1 ) {
fout << "p = " << i
<< ", s = " << m + n
<< ", m = " << m
<< ", n = " << n << endl;
}
}
}
void main()
{
useCon_1();
useCon_2();
useCon_3();
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991964/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 微軟最新面試題10.30微軟面試題
- 面試題 17.04. 消失的數字面試題
- 微軟面試題: LeetCode 151. 翻轉字串裡的單詞 出現次數:6微軟面試題LeetCode字串
- [leetcode/lintcode 題解] 微軟 面試題:實現 Trie(字首樹)LeetCode微軟面試題
- 微軟面試題: LeetCode 91. 解碼方法 出現次數:3微軟面試題LeetCode
- 百度/數字馬力面試題分享面試題
- Android面試題(轉載)Android面試題
- 面試程式碼題(vivo)數位之積面試
- 終結腦經急轉彎式問題,微軟面試流程大變革!微軟面試
- 軟體測試面試題(2)面試題
- Hadoop面試題之HDFSHadoop面試題
- Hadoop面試題之MapReduceHadoop面試題
- 字串轉數字的問題字串
- Python面試50題!面試鞏固必看!【轉】Python面試
- ●六數謎題●(8)
- ●六數謎題●(7)
- ●六數謎題●(10)
- ●六數謎題●(9)
- ●六數謎題●(13)
- ●六數謎題●(12)
- ●六數謎題●(1)
- ●六數謎題●(3)
- ●六數謎題●(2)
- ●六數謎題●(11)
- ●六數謎題●(16)
- ●六數謎題●(14)
- ●六數謎題●(15)
- ●六數謎題●(5)
- ●六數謎題●(4)
- ●六數謎題●(6)
- 資料結構和演算法面試題系列—數字題總結資料結構演算法面試題
- 軟體測試面試問題(一)面試
- 微軟的100道演算法面試題(終結版)微軟演算法面試題
- 面試題整理之Vue篇面試題Vue
- Java面試題:之ZooKeeper篇Java面試題
- Android面試題之Fragment篇Android面試題Fragment
- 面試題:布林變數面試題變數
- HTML最新面試題(筆試面試題)HTML面試題筆試
- 軟體測試經典面試題:如何測微信的朋友圈?面試題