CFGym 101192G. ReHanoi Towers

题意:给了四柱汉诺塔,求将一个柱子上的所有圆盘移到另一个柱子上的最小步数

分析:打表找规律。由于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;
}

猜你喜欢

转载自blog.csdn.net/zhlbjtu2016/article/details/81175000