zoukankan      html  css  js  c++  java
  • 九连环

    6760: 九连环

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 642  解决: 104
    [提交] [状态] [讨论版] [命题人:admin]

    题目描述

    九连环是一种源于中国的传统智力游戏。如图所示,九个圆环套在一把“剑”上,并且互相牵连。游戏的目标是把九个圆环从“剑”上卸下。
    圆环的装卸需要遵守两个规则。
    第一个(最右边)环任何时候都可以装上或卸下。
    如果第k个环没有被卸下,且第k个环右边的所有环都被卸下,则第k+1个环(第k个环左边相邻的环)可以任意装上或卸下。
    与魔方的千变万化不同,解九连环的最优策略是唯一的。为简单起见,我们以“四连环”为例,演示这一过程。这里用1表示环在“剑”上,0表示环已经卸下。
    初始状态为1111,每部的操作如下:
    1101(根据规则2,卸下第2个环)
    1100(根据规则1,卸下第1个环)
    0100(根据规则2,卸下第4个环)
    0101(根据规则1,装上第1个环)
    0111(根据规则2,装上第2个环)
    0110(根据规则1,卸下第1个环)
    0010(根据规则2,卸下第3个环)
    0011(根据规则1,装上第1个环)
    0001(根据规则2,卸下第2个环)
    0000(根据规则1,卸下第1个环)
    由此可见,卸下“四连环”至少需要10步。随着环数增加,需要的步数也会随之增多。例如卸下九连环,就至少需要341步。
    请你计算,有n个环的情况下,按照规则,全部卸下至少需要多少步。

    输入

    输入第一行为一个整数m ,表示测试点数目。
    接下来m行,每行一个整数n。

    输出

    输出共m行,对应每个测试点的计算结果。

    样例输入

    3
    3
    5
    9
    

    样例输出

    5
    21
    341
    

    提示

    对于10%的数据,1≤n≤10。
    对于30%的数据,1≤n≤30。
    对于100%的数据,1≤n≤105,1≤m≤10。

    来源/分类

    重庆OI2018 

    思路:通过找规律可知,n连环的最少步数是⌊(2^(n+1))/3⌋,剩下的就是套板子!
    AC代码:
    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    using namespace std;
    
    template <class T>
    void read(T &x)
    {
        char c;
        bool op=0;
        while(c=getchar(),c<'0'||c>'9')
        {
            if(c=='-')op=1;
        }
        x=c-'0';
        while(c=getchar(),c>='0' && c<='9')
        {
            x=x*10+c-'0';
        }
        if(op==1) x=-x;
    }
    
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'),x=-x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    const int N = 150000;
    const double PI = acos(-1);
    int T,x;
    
    struct cp
    {
        double a,b;
        cp(){}
        cp(double x, double y):a(x),b(y){}
        cp operator + (const cp &obj) const
        {
            return cp(a+obj.a,b+obj.b);
        }
        cp operator - (const cp &obj) const
        {
            return cp(a-obj.a,b-obj.b);
        }
        cp operator * (const cp &obj) const
        {
            return cp(a*obj.a-b*obj.b,a*obj.b+b*obj.a);
        }
    }inv[N],omg[N];
    
    void init(int n)
    {
        for(int i=0;i<n;i++)
        {
            omg[i]=cp(cos(2*PI/n*i),sin(2*PI/n*i));
            inv[i]=cp(omg[i].a,-omg[i].b);
        }
    }
    
    void fft(cp *a,int n,cp *omg)
    {
        int lim = 0;
        while((1<<lim)<n) lim++;
        for(int i=0;i<n;i++)
        {
            int t=0;
            for(int j=0;j<lim;j++)
            {
                if(i>>j&1) t|=1<<(lim-j-1);
            }
            if(i<t) swap(a[i],a[t]);
        }
        for(int l=2; l<=n; l<<=1)
        {
            int m=l/2;
            for(cp *p=a; p!=a+n; p+=l)
            {
                for(int i=0; i<m; i++)
                {
                    cp t=omg[n/l*i]*p[i+m];
                    p[i+m]=p[i]-t;
                    p[i]=p[i]+t;
                }
            }
        }
    }
    
    struct big
    {
        int g[N],len;
        big()
        {
            memset(g,0,sizeof(g));
            len=1;
        }
        big(int x)
        {
            memset(g,0,sizeof(g));
            len=0;
            if(!x)
            {
                len=1;
                return;
            }
            while(x) g[len++]=x%10,x/=10;
        }
        void out()
        {
            for(int i=len-1; i>=0; i--)
            {
                printf("%d",g[i]);
            }
            enter;
        }
        void operator /= (int x)
        {
            int sum=0, newlen=0;
            for(int i=len-1; i>=0; i--)
            {
                sum=sum*10+g[i];
                if(sum<x) g[i]=0;
                else
                {
                    if(!newlen) newlen=i+1;
                    g[i]=sum/x;
                    sum%=x;
                }
            }
            len=max(newlen,1);
        }
        void operator *= (const big &b)
        {
            static cp A[N], B[N];
            int newlen=len+b.len-1,n=1;
            while(n<newlen) n<<=1;
            for(int i=0; i<n; i++)
            {
                A[i]=cp(i<len ? g[i]:0,0);
                B[i]=cp(i<b.len ? b.g[i]:0,0);
            }
            init(n);
            fft(A, n, omg);
            fft(B, n, omg);
            for(int i=0; i<n; i++)
            {
                A[i]=A[i]*B[i];
            }
            fft(A, n, inv);
            for(int i=0; i<newlen; i++)
            {
                g[i]=(int)floor(A[i].a/n+0.5);
            }
            g[len=newlen]=0;
            for(int i=0; i<len; i++)
            {
                g[i+1]+=g[i]/10,g[i]%=10;
            }
            if(g[len]) len++;
        }
    }ret,a;
    
    int main()
    {
    
        read(T);
        while(T--)
        {
            read(x),x++;
            ret=big(1),a=big(2);
            while(x)
            {
                if(x&1) ret*=a;
                a*=a;
                x>>=1;
            }
            ret/=3;
            ret.out();
        }
        return 0;
    }
  • 相关阅读:
    IOS 给一个文本框,按钮,view加虚线边框
    AFNetworking 使用  基础篇
    IOS——中级篇 --TableView以及Cell
    IOS中级篇 —— picKerView and DatePicKer
    IOS中级篇 ——自动布局 Autolayout  and  VFL
    IOS中级篇—— 多线程--NSOperation
    IOS中级篇 —— Autoresizing
    IOS中级篇 —— 字典转模型
    IOS中级篇 —— 关于深复制和浅复制
    IOS中级篇 —— 日期时间对象
  • 原文地址:https://www.cnblogs.com/lglh/p/9439260.html
Copyright © 2011-2022 走看看