P4461 [CQOI2018]九连环(找规律,大数)

 

题目背景

九连环是一种源于中国的传统智力游戏。如图所示,九个的圆环套在一把“剑”上,并且互相牵连。游戏的目标是把九个圆环全部从“剑”上卸下。

题目描述

圆环的装卸需要遵守两个规则:

  1. 第一个(最右边) 环任何时候都可以任意装上或卸下

  2. 如果第k 个环没有被卸下,且第k 个环右边的所有环都被卸下,则第k+1个环(第k 个环左边相邻的环) 可以任意装上或卸下

与魔方的千变万化不同,解九连环的最优策略是唯一的。为简单起见,我们以“四连环”为例,演示这一过程。这里用1表示环在“剑”上,0 表示环已经卸下。

初始状态为1111,每步的操作如下:

  1. 1101 (根据规则2,卸下第2 个环)

  2. 1100 (根据规则1,卸下第1 个环)

  3. 0100 (根据规则2,卸下第4 个环)

  4. 0101 (根据规则1,装上第1 个环)

  5. 0111 (根据规则2,装上第2 个环)

  6. 0110 (根据规则1,卸下第1 个环)

  7. 0010 (根据规则2,卸下第3 个环)

  8. 0011 (根据规则1,装上第1 个环)

  9. 0001 (根据规则2,卸下第2 个环)

  10. 0000 (根据规则1,卸下第1 个环)

由此可见,卸下“四连环”至少需要10 步。随着环数增加,需要的步数也会随之增多。例如卸下九连环,就至少需要341步。

请你计算,有n 个环的情况下,按照规则, 全部卸下至少需要多少步。

输入输出格式

输入格式:

 

输入文件第一行,为一个整数m,表示测试点数目。

接下来m行,每行一个整数n。

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 复制

3
3
5
9

输出样例#1: 复制

5
21
341

说明

对于10%的数据, 1≤n≤101≤n≤10

对于30%的数据, 1≤n≤301≤n≤30

对于100%的数据, 1≤n≤10^5,1≤m≤101≤n≤105,1≤m≤10

 

找规律,大数,Java写了一个Python写了一个

import java.math.BigInteger;
import java.util.*;
 
import javax.security.auth.callback.LanguageCallback;
 
public class Main{
     
    public static void main(String[] args)
    {
        Scanner cin = new Scanner(System.in);
         
        BigInteger[] a = new BigInteger[5];
        a[0]=BigInteger.ONE;
        a[1]=a[0].add(a[0]);
        int m,n;
        m = cin.nextInt();
         
        for(int i=0;i<m;i++)
        {
            n = cin.nextInt();
            BigInteger x = a[1];
            for(int j=2;j<=n;j++)
            {
                if(j%2!=0)
                    x=x.multiply(a[1]);
                else
                    x=(x.multiply(a[1])).subtract(a[0]);
            }
            System.out.println(x.subtract(a[0]));
        }
         
    }
}
m = int(input())

for i in range(1,m+1):
    n = int(input())
    ans = 1
    for j in range(1,n+1):
        if(j%2):
            ans = ans*2
        else:
            ans = ans*2 - 1
    print(ans-1)

 

另一个通项公式

m = int(input())
for i in range(1,m+1):
    n = int(input())
    ans = 1
    ans = pow(2,n+1)
    if(n%2):
        ans = (ans-1)//3
    else:
        ans = (ans-2)//3
    print(ans)

 

c++的话要套大数板子,暂时还没写

贴一个大佬的大数板子

 

#include<bits/stdc++.h>
using namespace std;
 
//大整数
struct BigInteger
{
    static const int BASE=100000000;//和WIDTH保持一致
    static const int WIDTH=8;//八位一存储,如修改记得修改输出中的%08d
    bool sign;//符号, 0表示负数
    size_t length;
    vector<int> num;//反序存
//构造函数
    BigInteger (long long x = 0) { *this = x; }
    BigInteger (const string& x) { *this = x; }
    BigInteger (const BigInteger& x) { *this = x; }
//剪掉前导0
    void cutLeadingZero()
    {
        while(num.back() == 0 && num.size() != 1) { num.pop_back(); }
    }
//设置数的长度
    void setLength()
    {
        cutLeadingZero();
        int tmp = num.back();
        if(tmp == 0) { length = 1; }
        else
        {
            length = (num.size() - 1) * WIDTH;
            while(tmp > 0) { ++length; tmp /= 10; }
        }
    }
//赋值运算符
    BigInteger& operator = (long long x)
    {
        num.clear();
        if (x >= 0) sign = true;
        else { sign = false; x = -x; }
        do
        {
            num.push_back(x%BASE);
            x/=BASE;
        }while(x>0);
        setLength();
        return *this;
    }
//赋值运算符
    BigInteger& operator = (const string& str)
    {
        num.clear();
        sign = (str[0] != '-');//设置符号
        int x, len=(str.size()-1-(!sign))/WIDTH+1;
        for(int i=0;i<len;i++)
        {
            int End=str.length()-i*WIDTH;
            int start=max((int)(!sign), End-WIDTH);//防止越界
            sscanf(str.substr(start,End-start).c_str(),"%d",&x);
            num.push_back(x);
        }
        setLength();
        return *this;
    }
//赋值运算符
    BigInteger& operator = (const BigInteger& tmp)
    {
        num = tmp.num;
        sign = tmp.sign;
        length = tmp.length;
        return *this;
    }
 
 
//数的位数
    size_t size() const { return length; }
//*10^n 除法中用到
    BigInteger e(size_t n) const
    {
        int tmp = n % WIDTH;
        BigInteger ans;
        ans.length = n + 1;
        n /= WIDTH;
        while (ans.num.size() <= n) ans.num.push_back(0);
        ans.num[n] = 1;
        while (tmp--) ans.num[n] *= 10;
        return ans*(*this);
    }
//绝对值
    BigInteger abs() const
    {
        BigInteger ans(*this);
        ans.sign = true;
        return ans;
    }
//正号
    const BigInteger& operator + () const { return *this; }
// + 运算符
    BigInteger operator + (const BigInteger& b) const
    {
        if (!b.sign) { return *this - (-b); }
        if (!sign) { return b - (-*this); }
        BigInteger ans;
        ans.num.clear();
        for(int i=0,g=0;;i++)
        {
            if(g==0&&i>=num.size()&&i>=b.num.size()) break;
            int x=g;
            if(i<num.size()) x+=num[i];
            if(i<b.num.size()) x+=b.num[i];
            ans.num.push_back(x%BASE);
            g=x/BASE;
        }
        ans.setLength();
        return ans;
    }
//负号
    BigInteger operator - () const
    {
        BigInteger ans(*this);
        if (ans != 0) ans.sign = !ans.sign;
        return ans;
    }
// - 运算符
    BigInteger operator - (const BigInteger& b) const
    {
        if (!b.sign) { return *this + (-b); }
        if (!sign) { return -((-*this) + b); }
        if (*this < b) { return -(b - *this); }
        BigInteger ans;
        ans.num.clear();
        for(int i=0,g=0;;i++)
        {
            if(g==0&&i>=num.size()&&i>=b.num.size()) break;
            int x=g; g=0;
            if(i<num.size()) x+=num[i];
            if(i<b.num.size()) x-=b.num[i];
            if(x<0)
            {
                x+=BASE;g=-1;
            }
            ans.num.push_back(x);
        }
        ans.setLength();
        return ans;
    }
// * 运算符
    BigInteger operator * (const BigInteger& b) const
    {
        int lena = num.size(), lenb = b.num.size();
        vector<long long> ansLL;
        for (int i = 0; i < lena+lenb; i++) ansLL.push_back(0);
        for (int i = 0; i < lena; i++)
        {
            for (int j = 0; j < lenb; j++)
            {
                ansLL[i+j] += (long long)num[i]*(long long)b.num[j];
            }
        }
        while (ansLL.back() == 0 && ansLL.size() != 1) ansLL.pop_back();
        int len = ansLL.size();
        long long g = 0, tmp;
        BigInteger ans;
        ans.sign = (ansLL.size() == 1 && ansLL[0] == 0) || (sign == b.sign);
        ans.num.clear();
        for (int i = 0; i < len; i++)
        {
            tmp = ansLL[i];
            ans.num.push_back((tmp + g)%BASE);
            g = (tmp + g) / BASE;
        }
        if (g > 0) ans.num.push_back(g);
        ans.setLength();
        return ans;
    }
// / 运算符 (大数除小数)
    BigInteger operator / (const long long& b) const
    {
        BigInteger c;
        c.num.clear();
        for(int i=0;i<num.size();i++)
        {
            c.num.push_back(0);
        }
        long long g=0;
        for(int i=num.size()-1;i>=0;i--)
        {
            c.num[i]=(num[i]+g*BASE)/b;
            g=num[i]+g*BASE-c.num[i]*b;
        }
        for(int i=num.size()-1;c.num[i]==0;i--)
        {
            c.num.pop_back();
        }
        return c;
    }
// /运算符 (大数除大数)
    BigInteger operator / (const BigInteger& b) const
    {
 
        BigInteger aa((*this).abs());
        BigInteger bb(b.abs());
        if (aa < bb) return 0;
        char *str = new char[aa.size() + 1];
        memset(str, 0, sizeof(char)*(aa.size()+1));
        BigInteger tmp;
        int lena = aa.length, lenb = bb.length;
        for (int i = 0; i <= lena - lenb; i++)
        {
            tmp = bb.e(lena - lenb - i);
            while (aa >= tmp)
            {
                ++str[i];
                aa = aa - tmp;
            }
            str[i] += '0';
        }
        BigInteger ans(str);
        delete[]str;
        ans.sign = (ans == 0 || sign == b.sign);
        return ans;
    }
// % 运算符 (大数取模小数)
    BigInteger operator % (const long long& b) const
    {
        long long ans=0,lena=num.size();
        for(int i=lena-1;i>=0;i--)
        {
            ans=(ans*BASE+num[i])%b;
        }
        return ans;
    }
// %运算符 (大数取模大数)
    BigInteger operator % (const BigInteger& b) const
    {
        return *this - *this / b * b;
    }
 
    BigInteger& operator ++ () { *this=*this+1;return *this; } // ++ 运算符
    BigInteger& operator -- () { *this=*this-1;return *this; } // -- 运算符
    BigInteger& operator += (const BigInteger& b) { *this=*this+b;return *this; } // += 运算符
    BigInteger& operator -= (const BigInteger& b) { *this=*this-b;return *this; } // -= 运算符
    BigInteger& operator *= (const BigInteger& b) { *this=*this*b;return *this; } // *=运算符
    BigInteger& operator /= (const long long& b)  { *this=*this/b;return *this; } // /=运算符
    BigInteger& operator /= (const BigInteger& b) { *this=*this/b;return *this; } // /= 运算符
    BigInteger& operator %= (const long long& b)  { *this=*this%b;return *this; } // %=运算符
    BigInteger& operator %= (const BigInteger& b) { *this=*this%b;return *this; } // %=运算符
// < 运算符
    bool operator < (const BigInteger& b) const
    {
        if (sign && !b.sign) { return false; }//正负
        else if(!sign && b.sign) { return true; }//负正
        else if(!sign && !b.sign) { return -b < -*this; }//负负
        //正正
        if(num.size()!=b.num.size()) return num.size()<b.num.size();
        for(int i=num.size()-1;i>=0;i--)
            if(num[i]!=b.num[i]) return num[i]<b.num[i];
        return false;
    }
 
    bool operator >  (const BigInteger& b) const { return b<*this; }              // >  运算符
    bool operator <= (const BigInteger& b) const { return !(b<*this); }           // <= 运算符
    bool operator >= (const BigInteger& b) const { return !(*this<b); }           // >= 运算符
    bool operator != (const BigInteger& b) const { return b<*this||*this<b; }     // != 运算符
    bool operator == (const BigInteger& b) const { return !(b<*this)&&!(*this<b); }//==运算符
 
    bool operator || (const BigInteger& b) const { return *this != 0 || b != 0; } // || 运算符
    bool operator && (const BigInteger& b) const { return *this != 0 && b != 0; } // && 运算符
    bool operator !  () { return (bool)(*this == 0); }                            // ! 运算符
 
    //重载<<使得可以直接输出大数
    friend ostream& operator << (ostream &out,const BigInteger &x)
    {
        if (!x.sign) out<<'-';
        out<<x.num.back();
        for(int i=x.num.size()-2;i>=0;i--)
        {
            char buf[10];
            //如WIDTH和BASR有变化,此处要修改为%0(WIDTH)d
            sprintf(buf,"%08d",x.num[i]);
            for(int j=0;j<strlen(buf);j++) out<<buf[j];
        }
        return out;
    }
    //重载>>使得可以直接输入大数
    friend istream& operator >> (istream &in, BigInteger &x)
    {
        string str;
        in >> str;
        size_t len = str.size();
        int i, start = 0;
        if (str[0] == '-') start = 1;
        if (str[start] == '\0') return in;
        for (int i = start; i < len; i++)
        {
            if (str[i] < '0' || str[i] > '9') return in;
        }
        x.sign = !start;
        x = str.c_str();
        return in;
    }
 
};
 
BigInteger qpow(int b)
{
    BigInteger ans=1,a=2;
    while(b)
    {
        if(b&1)
            ans=(ans*a);
        a=(a*a);
        b/=2;
    }
    return ans;
}
 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
 
        BigInteger a=1;
        a=qpow(n+1);
 
        if(n%2)
            a=(a-1)/3;
        else
            a=(a-2)/3;
 
        cout<<a<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值