题目背景
九连环是一种源于中国的传统智力游戏。如图所示,九个的圆环套在一把“剑”上,并且互相牵连。游戏的目标是把九个圆环全部从“剑”上卸下。
题目描述
圆环的装卸需要遵守两个规则:
-
第一个(最右边) 环任何时候都可以任意装上或卸下
-
如果第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行,对应每个测试点的计算结果。
输入输出样例
输入样例#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;
}