题目:http://acm.hdu.edu.cn/showproblem.php?pid=1210
暴力法。。超时了。。。
#include<iostream>
using namespace std;
int f[100009];
int main()
{
int n;
int t=1;
int ans;
for(n=1;n<=100001;n++)
{
ans=0;
t=1;
while(1)
{
if(t<=n)
{
ans++;
t=t*2;
}
if(t==(n+1))
break;
if(t>n+1)
{
int k=t%n;
if(k==0)
k=n;
t=1+(k-1)*2;
ans++;
}
if(t==(n+1))
break;
}
f[n]=ans+1;
// printf("%d\n",ans+1);
}
while(cin>>n)
printf("%d\n",f[n]);
return 0;
}
额。。。悲剧。。原来方法是对的。。。但是不用预处理1-100000之间的结果!!
方法就是跟随1 ,模拟1到达的位置,当1到n+1位置时 的方法数+1就等于所求的结果!
例如 :模拟 n= 3 时 1的状态。
初始 1 2 3 4 5 6 //t=1 初始位置
因为t在n的左边 那么他的下次位置就在 t=t*2;
所以第一次洗牌 就为 4 1 5 2 6 3 //t=2
同理第 二次 2 4 6 1 3 5 //t=4;
当在n右边时,t的下次位置就跟当前在n右边的位置有关。。。 t的下次位置为 1 ,3, 5, 7, 9......
所以就用k代表 当前所在n右边的第几个位置。。容易得出下一步t的值。
那么第三次 为 1 2 3 4 5 6
完毕。
下面是AC代码:
#include<iostream>
using namespace std;
int main()
{
int n;
int t=1;
int ans;
while(cin>>n)
{
ans=0;
t=1;
while(1)
{
if(t<=n)
{
ans++;
t=t*2;
}
if(t==(n+1))
break;
if(t>n+1)
{
int k=t%n;
if(k==0)
k=n;
t=1+(k-1)*2;
ans++;
}
if(t==(n+1))
break;
}
printf("%d\n",ans+1);
}
return 0;
}