编程题目的讨论
在1742年给欧拉的信中哥德巴赫提出了以下猜想:任一大于2的整数都可写成三个质数之和。但是哥德巴赫自己无法证明它,于是就写信请教赫赫有名的大数学家欧拉帮忙证明,但是一直到死,欧拉也无法证明。因现今数学界已经不使用“1也是素数”这个约定,原初猜想的现代陈述为:任一大于5的整数都可写成三个质数之和。欧拉在回信中也提出另一等价版本,即任一大于2的偶数都可写成两个质数之和。今日常见的猜想陈述为欧拉的版本。把命题"任一充分大的偶数都可以表示成为一个素因子个数不超过a个的数与另一个素因子不超过b个的数之和"记作"a+b"。1966年陈景润证明了"1+2"成立,即"任一充分大的偶数都可以表示成二个素数的和,或是一个素数和一个半素数的和"。
两个素数之和本来就是偶数,也就说找到所有的素数,然后两两相加,时间复杂度o(n*n),需要2n的空间。
知道哥德巴赫猜想答案就出来了吗?
大于6的偶数的确都能用素数和表示, 但是相加的两个数中可能恰恰包含被刨除的3和5考虑了吗?
没有了3和5, 如果相加的两个素质只能用相同的两个素数相加, 题里允许了吗? (比如14, 不能3+11, 那么7+7允许吗)
扔出一个哥德巴赫猜想就好像答案已经出来了, 连题意和输入都不能静下心仔细确定好的, 这个比不懂某方面知识捉急多了
概念题,每次抽取只会有三个结果:
一红一蓝
两蓝
两红
由于每次取球只能是0个或者2个,所以最后剩球只会是两个,那么题意是要求得到最后一次取球为一红一蓝的概率。
为了最后剩余一红一蓝,则前面不能出现两蓝的情况,比如第一次出现两蓝,那么剩余18蓝加20红,这样就无论如何不会最后剩余一红一蓝了,最多两红(这里最难理解了,多想一想)
所以,要想最后剩余一红一蓝,必须每次取出的都是一红一蓝,那么概率是:
(1/20 * 20/39) * (1/19 * 19/38) * (1/18 * 18/37)
即:
(1/(n - k) * (n - k)/(2*n - 1 - k))
n=20
k=0,1,2,...,18
上面稍有点问题,结论应该是:
要想最后剩余一红一蓝,必须每次取出的都是一红一蓝或者两红,那么概率是:
(1/20 * 20/39 + 1/20*19/39) * (1/19 * 19/38 + 1/20*19/39) ...
1 #include <stdio.h>
2 #include <string.h>
3 #include <math.h>
4 #include <time.h>
5
6 #include <set>
7 #include <vector>
8
9 #define MAXNUMBER 1000000
10
11 bool is_prime (int x)
12 {
13 int i,t;
14 if (x<=1 || 0==x%2)
15 {
16 return false;
17 }
18 t = (int)sqrt (x+0.0f);
19 for (i=3;i<=t;i+=2)
20 {
21 if (0 == x%i)
22 {
23 return false;
24 }
25 }
26 return true;
27 }
28
29 int main(void)
30 {
31 std::vector<int> prime_Value;
32 prime_Value.reserve(50000);
33 std::set<int> value_set;
34 prime_Value.push_back(7);
35 prime_Value.push_back(11);
36
37 int max_sum=18;
38 time_t timenow =time(NULL);
39 for (int i =13 ;i < MAXNUMBER;i+=2)
40 {
41 if (is_prime(i))
42 {
43 int max_prime =prime_Value[prime_Value.size()-1];
44 std::set<int> tmp_set;
45
46 for (int j = max_sum+2 ;j<max_prime+i;j+=2)
47 {
48 tmp_set.insert(j);
49
50 }
51 for (int j =0 ;j< prime_Value.size();j++)
52 {
53 int tmp_value = prime_Value[j]+i;
54 std::set<int>::iterator iter = value_set.find(tmp_value);
55 if (iter!=value_set.end())
56 {
57 value_set.erase(iter);
58 }
59 else
60 {
61 iter = tmp_set.find(tmp_value);
62 if (iter!=tmp_set.end())
63 tmp_set.erase(iter);
64 }
65
66 }
67 prime_Value.push_back(i);
68 value_set.insert(tmp_set.begin(),tmp_set.end());
69
70 max_sum = max_prime+i;
71
72 }
73 }
74 int spend = time(NULL)-timenow;
75 printf("spend %d sec ,prime_size=%d,value_size=%d\n",spend,prime_Value.size(),value_set.size());
76 std::set<int>::iterator iter;
77 int max_prime =prime_Value[prime_Value.size()-1];
78 int sec_prime =prime_Value[prime_Value.size()-2];
79 printf("max_prime= %d,sec_prime=%d \n",max_prime,sec_prime);
80
81 for (iter=value_set.begin();iter!= value_set.end();iter++)
82 {
83 printf("%d is not in list \n",*iter);
84 }
85 getchar();
86 return 0;
87
88
89 }
今天下午面了百度,其中两题是这样的,我都没有回答出来。
概率题:一个篮子里装着20个红球和20个蓝球,每次从中取出2球,如果取出的2球颜色是不一样的,那么放回红球,取出蓝球;如果取出的2球的颜色是一样的,则都不放回,将2球都取出;不断重复以上步骤。问题:求最后一次取球恰好只取到一个红球的概率。
算法题:给你一个自然数N,求[6,N]之内的所有素数中,两两之和为偶数的那些偶数。(直接枚举的话应该是O(n^2))。我的解法如下,是直接枚举的。
1 /* 百度面试题 */
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #define N (20000)
6 #define M (N/2)
7
8 static int primes[M]; /*编译器初始化了0*/
9 static int sums[M*M]; /*任意两素数之和*/
10 int my_cmp (const void * a, const void * b);
11
12 /* 判断一个数是不是素数,是素数则返回它自己;否则返回0 */
13 int is_prime (int x){
14 int i,t;
15 int ans = 0;
16 if (x<=1 || 0==x%2){
17 return ans;
18 }
19 t = (int)sqrt (x);
20 for (i=3;i<=t;i+=2){
21 if (0 == x%i){
22 return ans;
23 }
24 }
25 return (ans = x);
26 }
27
28 /* 保存区间的素数到全局数组primes */
29 void primes_in (int low, int high){
30 int i=0,j=low;
31 while (j<=high){
32 if (is_prime (j)){
33 primes[i++]=j;
34 }
35 j++;
36 }
37 }/*数组中的非零元素就是区间中的素数 */
38
39 /*求区间中素数的和并打印出来 */
40 void solve (int left, int right){
41 int i,j,k;
42 int t;
43 primes_in (left,right);
44 for (t=0; t<M; t++){
45 if (!primes[t]){
46 break;
47 }
48 }
49 for (k=0,i=0; i<t; i++){
50 for (j=i; j<t; j++){
51 sums[k++]=primes[i]+primes[j];
52 }
53 }
54 /*排序*/
55 qsort (sums, k, sizeof (int), my_cmp);
56 /*去重*/
57 i=0;
58 for (j=i+1; j<k; j++){
59 if (sums[j] > sums[i]){
60 sums[++i] = sums[j];
61 }
62 }
63 /*打印*/
64 for (j=0;j<=i;j++){
65 printf ("%d, %d\n", j+1, sums[j]);
66 }
67 }
68
69 int my_cmp (const void * a, const void * b){
70 return (*(int *)a - *(int *)b);
71 }
72
73
74 /* 程序入口 */
75 int main (){
76 solve (6,N);
77 return 0;
78
79 }