您的位置:首页 > 编程语言

编程题目的讨论

2013-08-16 22:18 120 查看
在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) ...

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>

#include <set>
#include <vector>

#define MAXNUMBER 1000000

bool is_prime (int x)
{
int i,t;
if (x<=1 || 0==x%2)
{
return false;
}
t = (int)sqrt (x+0.0f);
for (i=3;i<=t;i+=2)
{
if (0 == x%i)
{
return false;
}
}
return true;
}

int main(void)
{
std::vector<int> prime_Value;
prime_Value.reserve(50000);
std::set<int> value_set;
prime_Value.push_back(7);
prime_Value.push_back(11);

int max_sum=18;
time_t timenow =time(NULL);
for (int i =13 ;i < MAXNUMBER;i+=2)
{
if (is_prime(i))
{
int max_prime =prime_Value[prime_Value.size()-1];
std::set<int> tmp_set;

for (int j = max_sum+2 ;j<max_prime+i;j+=2)
{
tmp_set.insert(j);

}
for (int j =0 ;j< prime_Value.size();j++)
{
int tmp_value = prime_Value[j]+i;
std::set<int>::iterator iter =  value_set.find(tmp_value);
if (iter!=value_set.end())
{
value_set.erase(iter);
}
else
{
iter =  tmp_set.find(tmp_value);
if (iter!=tmp_set.end())
tmp_set.erase(iter);
}

}
prime_Value.push_back(i);
value_set.insert(tmp_set.begin(),tmp_set.end());

max_sum = max_prime+i;

}
}
int spend = time(NULL)-timenow;
printf("spend %d sec ,prime_size=%d,value_size=%d\n",spend,prime_Value.size(),value_set.size());
std::set<int>::iterator iter;
int max_prime =prime_Value[prime_Value.size()-1];
int sec_prime =prime_Value[prime_Value.size()-2];
printf("max_prime= %d,sec_prime=%d \n",max_prime,sec_prime);

for (iter=value_set.begin();iter!= value_set.end();iter++)
{
printf("%d is not in list \n",*iter);
}
getchar();
return 0;

}


今天下午面了百度,其中两题是这样的,我都没有回答出来。
概率题:一个篮子里装着20个红球和20个蓝球,每次从中取出2球,如果取出的2球颜色是不一样的,那么放回红球,取出蓝球;如果取出的2球的颜色是一样的,则都不放回,将2球都取出;不断重复以上步骤。问题:求最后一次取球恰好只取到一个红球的概率。

算法题:给你一个自然数N,求[6,N]之内的所有素数中,两两之和为偶数的那些偶数。(直接枚举的话应该是O(n^2))。我的解法如下,是直接枚举的。

/* 百度面试题 */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define N (20000)
#define M (N/2)

static int primes[M]; /*编译器初始化了0*/
static int sums[M*M]; /*任意两素数之和*/
int my_cmp (const void * a, const void * b);

/* 判断一个数是不是素数,是素数则返回它自己;否则返回0 */
int is_prime (int x){
int i,t;
int ans = 0;
if (x<=1 || 0==x%2){
return ans;
}
t = (int)sqrt (x);
for (i=3;i<=t;i+=2){
if (0 == x%i){
return ans;
}
}
return (ans = x);
}

/* 保存区间的素数到全局数组primes */
void primes_in (int low, int high){
int i=0,j=low;
while (j<=high){
if (is_prime (j)){
primes[i++]=j;
}
j++;
}
}/*数组中的非零元素就是区间中的素数 */

/*求区间中素数的和并打印出来 */
void solve (int left, int right){
int i,j,k;
int t;
primes_in (left,right);
for (t=0; t<M; t++){
if (!primes[t]){
break;
}
}
for (k=0,i=0; i<t; i++){
for (j=i; j<t; j++){
sums[k++]=primes[i]+primes[j];
}
}
/*排序*/
qsort (sums, k, sizeof (int), my_cmp);
/*去重*/
i=0;
for (j=i+1; j<k; j++){
if (sums[j] > sums[i]){
sums[++i] = sums[j];
}
}
/*打印*/
for (j=0;j<=i;j++){
printf ("%d, %d\n", j+1, sums[j]);
}
}

int my_cmp (const void * a, const void * b){
return (*(int *)a - *(int *)b);
}

/* 程序入口 */
int main (){
solve (6,N);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: