题意:给了四柱汉诺塔,求将一个柱子上的所有圆盘移到另一个柱子上的最小步数
分析:打表找规律。由于n是1e9,肯定不能递归,打表发现结果相邻分别是2,2,4,4,4,8,8,8,8...由于2个2,3个4...x个2^(x-1)。把每一个2的幂看成一组,求第n个数则找到之前有多少完整的组,直接加上,剩下的都相同直接加即可。1+2+...+n = (n+1)*n/2 。复杂度O(根号n)
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
typedef long long ll;
ll mod = 1e9 + 7;
int f[maxn];
ll mod_pow(ll x, ll n)
{
ll res = 1;
while(n > 0)
{
if(n & 1)res = res * x % mod;//如果二进制最低位为1就乘上x ^(2^i)
x = x * x % mod;//将X平方,因为每移一位就相当于指数乘以2
n >>= 1;
}
return res;
}
void dabiao()
{
f[1] = 1;f[2] = 3;
for(int i = 3; i <= 65; i++)
{
int minx = INF;
for(int j = 1; j < i; j++)
{
minx = min(minx,2 * f[j] + (int)pow(2,i - j) - 1);
}
f[i] = minx;
}
// for(int i = 1; i < 30; i++)
// {
// printf("i:%d num:%d dis:%d\n",i,f[i],f[i + 1] - f[i]);
// }
}
int main()
{
dabiao();
ll n,ans = 0;
cin>>n;
ll j = 1;
for(ll i = 0; i < n;)
{
if(i + j <= n)
{
ans += (mod_pow(2,j - 1) * j) % mod;
i += j;
j++;
//printf("i:%I64d j:%I64d ans:%I64d\n",i,j,ans);
}
else
{
for(;i < n; i++)
ans = (ans + mod_pow(2,j - 1)) % mod;
// printf("i:%I64d ans:%I64d\n",i,ans);
}
}
cout<<ans<<endl;
return 0;
}