有一种小虫,每隔两秒钟分裂一次。分裂后的两只新的小虫经过两秒钟后又会分裂。如果最
初某瓶中只有一只小虫,那么两秒后变两只,再过两秒后就变四只……两分钟后,正好满满
一瓶小虫。现在这个瓶内最初放入两只这样的小虫。问:经过多少时间后,正巧也是满满的一瓶?那位高手帮忙给个解题思路和Java解题算法代码。
初某瓶中只有一只小虫,那么两秒后变两只,再过两秒后就变四只……两分钟后,正好满满
一瓶小虫。现在这个瓶内最初放入两只这样的小虫。问:经过多少时间后,正巧也是满满的一瓶?那位高手帮忙给个解题思路和Java解题算法代码。
解决方案 »
- java swt中用GC在Canvas上画出一条直线后,怎么才能把这条直线去掉????
- 如何能读写PDF文件
- 请教:这个类为什么不可以序列化
- 文件遍历问题
- test
- "g.getFont().getName()"????不太明白?两个方法可以连继调用!
- java初学看什么书好啊?
- 要实现JTestArea 的滚动条,是不是必须用jScrollPane
- A try block must always be followed by a catch block ? 对么???
- jPasswordField 用getpassword().toString 问题 为什么它每次拿出来的字符不一样啊???
- 竞赛题目、求牛人解答、
- 查找时间
get(2,0);
}
public static void get(int starNum,int second){
if(second<120){
if(second%2==0){
starNum += starNum*2;
second += 2;
System.out.println("第"+second+"秒,有"+starNum+"条虫子!");
get(starNum,second);
}
}
}
[/Quote]
那就118秒没错了 没什么好想的了 更不用什么代码了
两只虫子的情况,只是第0秒就已经一只虫子的第2秒时的数量,都是按2的N次幂的数量级增长,那么到120s-2s时不就是一只虫子120s时的数量了吗?
还是兔子问题经典
public static void main(String args[]){
double f = 2;
double t = 1;
double p = 0;
for(int i=1; i<=120; i++){
t = 2 * t;
}
while(f <= t){
f = f * 2;
p++;
}
//int m = p/60;
System.out.println("初始两只需要" + p + "秒");
//System.out.println("也即" + m +"分");
}
}
菜鸟来凑热闹...,写完以后感觉容易出错的就是初始化的时候要用较高的精度而已,其他的不论是算法,或者是语言表述,都没什么问题,你是哪个公司的面试啊?
假设现有一条虫子, 分裂0次, 2^0,分裂 1 次, 2^1 个, 分裂 2 次, 2^2……分裂 n 次, 2^n个。
由于1条虫放在一个空瓶子中分裂了120s之后瓶满(每2s分裂一次,所以共分裂了 120/2 次),如设瓶中最多可容纳N条虫, 那么 N = 2 ^ (120/2)。 N = 2 ^ 60。 若开始在空瓶中放入2条虫,设经过t(s)之后,瓶满。则:
2^(t/2)*2 = N ==> 2^(t/2+1) = N ==> 2^(t/2+1) = 2 ^ 60 ==> t/2+1 = 60 ==> t = 118
所以, 是 118 s。
这似乎也用不到Java啊?!
using namespace std;
int main()
{
int t=0;
double j;
double s=1;
int i;
for(i=0;i<60;i++)
{
s=s*2;
}
for(j=2;j<=s;j++)
{
j=j*2;
t++;
}
printf("总虫数s=%f 貌似有几位被和谐了?!哈哈\n",s);
//cout<<s<<endl;
cout<<"时间t="<<2*t<<endl;
/*
cout<<s<<endl;
cout<<sizeof(long int);
cout<<sizeof(float)<<endl;
cout<<sizeof(double)<<endl;
cout<<sizeof(long double)<<endl;
*/
return 0;
}
运行结果:
总虫数s=1152921504606847000.000000 貌似有几位被和谐了?!哈哈
时间t=118
Press any key to continue虽然2^60的确超出了double型所提供的15~16位有效数字,但在本题中是一个凑巧,原因如下:
2^60=1152921504606846976
s=1152921504606847000
2^59=576460752303423488
576460752303423488*2>s
for循环刚好结束,所以也能算出时间t。但是要输出虫子数的精确值,还得自己定义数据类型
public class Insect { /**
* @param args
*/
public static double insectNum(int x,int second){//计算虫子总数
int temp=0;
double insectNumber=x;
while(temp<(second/2)){
insectNumber=insectNumber*2;
temp++;
}
return insectNumber;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//两次分裂中瓶子中的虫子的总数是相同的只是,只是开始分裂的时候初始值不一样,一个设定的是1,另一个设定的是2;
//两次的递增都是按照2的幂开始递增的
double b=insectNum(1,120);//计算总数
double a=2;
int j=0;//记录分裂的次数
while(a!=b){
a=a*2;
j++;
}
System.out.println(j*2);
}}
显而易见:
初始虫子个数 需要时间
2^0个 ----- 2*60秒
2^1个 ----- 2*59秒
2^2个 ----- 2*58秒
2^3个 ----- 2*57秒
.
.
.
2^59个 ----- 2*1秒
2^60个 ----- 2*0秒
这时候,答案显而易见,我们看下二进制数据对应情况:
1 1 2*60秒
2 01 2*59秒
3 11 2*59秒
4 100 2*58秒
5 101 2*58秒
6 110 2*58秒
7 111 2*58秒
8 1000 2*57秒
结论是:初始虫子数的二进制位数 + 所需秒数 / 2 = 61
而初始虫子数的二进制位数可以通过64-Long.numberOfLeadingZeros(虫子个数)得出;
故时间为122 - 2*初始虫子数二进制位数。具体方法如下:
/**
* 初始num个虫子的情况下,获取充满整个瓶子需要的时间
* @param num 初始虫子数
* @return 需要时间
*/
private static int getTime(long num){
int i = 64-Long.numberOfLeadingZeros(num);//首先获取初始虫子数的位数
return 122 - (i << 1);//i左移一位,即i*2
}
并且整个瓶子最多有2^60个虫子,所以只用long完全可以解决问题。
第二次是2*2*2*2*2*2……
每乘一次花费的时间是2秒,同样的量少乘一次2说明少用两秒。
他们考得应该就是基本数据类型的最大值,用int肯定不行。就是判断long是否可以。
long的取值范围为(-9223372036854774808~9223372036854774807),占用8个字节(-2的63次方到2的63次方-1。
这次运算最大的是2的60次方,所以用long应该可以。