<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">zoj 1088题目题目大意是,对n栋楼停电,先停第一栋,再隔m栋停一栋。数到最后一栋后从头循环计数,已经断电的不参与计数。要选取适当的m,使得即使其他楼都没电了,但第二栋楼仍然有电。 </span>
如果将该题视为普通的模拟算法,其时间复杂度将高达O(m*n)。由于题目给了很充足的时间和很小的m、n范围,一般的模拟算法即可完成。但有没有更高效的算法呢。
常见的优化方法是每断掉一栋楼的电,问题规模就减一,这样时间复杂度就降到了O(n)。 下面转帖内容:
一般使用这种方法的C/C++时间消耗在20ms以上,占用内存大概在272kB左右。
还可以使用j(2^n)=1的特性来优化计算,即对于原问题,对于n=2^p的情况,直接输出1而避免计算。 最后消耗时间0,空间168kb(c/c++消耗等同)。
下面贴出本人的原代码。这个算法已经非常接近最佳排行160KB。但是不知道如何继续降低空间消耗。 希望在学完COM一书后能有优化。
#include<cstdio> using namespace std; //Arthur::Xiaoqiang AN int joseph(int k,int b) { int res=0; for(int i=2;i<=k;++i) res=(res+b)%i; return res; } int main() { int n,t; while(scanf("%d",&n),n) { t=n-1; if(t==2||t==4||t==8||t==16||t==32||t==64||t==128) { printf("2\n"); continue; } else { for(int m=3;;++m) if(joseph(t,m)==0) { printf("%d\n",m); break; } } } }
如果直接模拟,然后输出所有结果到数组,最后备查的话,也可以将时间降为0,但空间消耗可能会大于168KB。 本人用自己前面的代码,将结果输出到文本,并重新查表输出的代码如下:
(为vim打个广告, 将输出结果改造为数组值的过程全部使用vim实现,最多只需要十次以内的操作,一分钟就能搞定,强烈推荐使用vim编程)。
#include<stdio.h>
int main()
{
int m[153];
m[0]=-1;
m[1]=-1;
m[2]=-1;
m[3]=2;
m[4]=5;
m[5]=2;
m[6]=4;
m[7]=3;
m[8]=11;
m[9]=2;
m[10]=3;
m[11]=8;
m[12]=16;
m[13]=4;
m[14]=21;
m[15]=6;
m[16]=5;
m[17]=2;
m[18]=11;
m[19]=20;
m[20]=34;
m[21]=8;
m[22]=15;
m[23]=10;
m[24]=7;
m[25]=13;
m[26]=11;
m[27]=13;
m[28]=45;
m[29]=18;
m[30]=23;
m[31]=8;
m[32]=3;
m[33]=2;
m[34]=25;
m[35]=75;
m[36]=42;
m[37]=13;
m[38]=5;
m[39]=23;
m[40]=13;
m[41]=50;
m[42]=16;
m[43]=18;
m[44]=89;
m[45]=38;
m[46]=8;
m[47]=39;
m[48]=30;
m[49]=29;
m[50]=38;
m[51]=7;
m[52]=45;
m[53]=23;
m[54]=137;
m[55]=46;
m[56]=63;
m[57]=17;
m[58]=48;
m[59]=5;
m[60]=46;
m[61]=34;
m[62]=140;
m[63]=33;
m[64]=39;
m[65]=2;
m[66]=28;
m[67]=29;
m[68]=79;
m[69]=33;
m[70]=48;
m[71]=3;
m[72]=10;
m[73]=46;
m[74]=120;
m[75]=6;
m[76]=37;
m[77]=17;
m[78]=8;
m[79]=44;
m[80]=15;
m[81]=160;
m[82]=20;
m[83]=35;
m[84]=144;
m[85]=104;
m[86]=179;
m[87]=153;
m[88]=24;
m[89]=8;
m[90]=265;
m[91]=19;
m[92]=9;
m[93]=62;
m[94]=7;
m[95]=139;
m[96]=19;
m[97]=44;
m[98]=93;
m[99]=182;
m[100]=27;
m[101]=158;
m[102]=185;
m[103]=193;
m[104]=17;
m[105]=82;
m[106]=3;
m[107]=11;
m[108]=43;
m[109]=55;
m[110]=21;
m[111]=41;
m[112]=146;
m[113]=29;
m[114]=80;
m[115]=59;
m[116]=8;
m[117]=29;
m[118]=66;
m[119]=19;
m[120]=160;
m[121]=59;
m[122]=28;
m[123]=129;
m[124]=127;
m[125]=120;
m[126]=72;
m[127]=45;
m[128]=157;
m[129]=2;
m[130]=63;
m[131]=127;
m[132]=81;
m[133]=318;
m[134]=513;
m[135]=98;
m[136]=28;
m[137]=32;
m[138]=231;
m[139]=236;
m[140]=411;
m[141]=26;
m[142]=45;
m[143]=5;
m[144]=303;
m[145]=228;
m[146]=66;
m[147]=9;
m[148]=205;
m[149]=65;
m[150]=39;
m[151]=16;
int n;
while(scanf("%d",&n),n)
{
printf("%d\n",m[n]);
}
return 0;
}
原文:http://blog.csdn.net/al5hn/article/details/43021301