九连环

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

圆环的装卸需要遵守两个规则。
第一个(最右边)环任何时候都可以装上或卸下。
如果第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行,对应每个测试点的计算结果。

 

分析:

写出规律:

规律:

       奇数 : a[i]= a[i-1]*2+1;       偶数:a[i]=a[i-1]*2; 因为数值已经爆long long 型,所以可以使用java 大数直接调用java的函数来写,也可以c++大整数类的相关运算 来解决,也可以c 语言手动模拟四则运算来写。

1.java大数:

import java.util.*;
import java.math.*;
 
public class dashu{
	public static void main(String[] args) {
		int m,n;
		Scanner cin=new Scanner(System.in);
		m=cin.nextInt();
	    while(m>0) {
	    	m--;
	    	n=cin.nextInt();
	    	if(n==1)
	    		System.out.println("1");
	    	else
	    	{
	    		BigInteger s;
	    		BigInteger a=BigInteger.valueOf(1);
	    		BigInteger b=BigInteger.valueOf(2);
	    		s=a;
	    		for(int i=2;i<=n;i++)
	    	    {
 
	    	        if(i%2==0)
	    	            s=s.multiply(b);
	    	        else{
	    	        	s=s.multiply(b);
	    	        	s=s.add(a);
	    	        }
	    	    }
	    		System.out.println(s);
	    	}
	    }
	    
	    
	}
}

2.c++使用大整数类的模板来写(重载运算符)这种做法,还未进行理解,等会再看

#include<bits/stdc++.h>
using namespace std;
const int ten[4]= {1,10,100,1000};
const int max1=10000;
struct BigNumber
{
    int d[max1];
    BigNumber (string s)
    {
        int len=s.size();
        d[0]=(len-1)/4+1;
        int i,j,k;
        for(i=1; i<max1; i++)
            d[i]=0;
        for(i=len-1; i>=0; i--)
        {
            j=(len-i-1)/4+1;
            k=(len-i-1)%4;
            d[j]+=ten[k]*(s[i]-'0');
        }
        while(d[0]>1&&d[d[0]]==0)
            --d[0];
 
    }
    BigNumber(){
        *this=BigNumber(string("0"));
    }
    string toString(){
        string s("");
        int i,j,temp;
        for(i=3; i>=1; i--)
            if(d[d[0]]>=ten[i])
                break;
        temp=d[d[0]];
        for(int j=i; j>=0; j--){
            s=s+(char)(temp/ten[j]+'0');
            temp%=ten[j];
        }
        for(i=d[0]-1; i>0; i--){
            temp=d[i];
            for(int j=3; j>=0; j--){
                s=s+(char)(temp/ten[j]+'0');
                temp%=ten[j];
            }
        }
        return s;
    }
} zero("0"),one("1"),two("2"),three("3"),mid1[2000],d,temp;
BigNumber operator +(const BigNumber &a,const BigNumber &b)
{
    BigNumber c;
    c.d[0]=max(a.d[0],b.d[0]);
    int i,x=0;
    for(i=1; i<=c.d[0]; ++i){
        x=a.d[i]+b.d[i]+x;
        c.d[i]=x%10000;
        x/=10000;
    }
    while(x!=0){
        c.d[++c.d[0]]=x%10000;
        x/=10000;
    }
    return c;
}
BigNumber operator *(const BigNumber &a,const BigNumber &b)
{
    BigNumber c;
    c.d[0]=a.d[0]+b.d[0];
    int i,j,x;
    for(i=1; i<=a.d[0]; i++){
        x=0;
        for(j=1; j<=b.d[0]; j++){
            x=a.d[i]*b.d[j]+x+c.d[i+j-1];
            c.d[i+j-1]=x%10000;
            x/=10000;
        }
        c.d[i+b.d[0]]=x;
    }
    while( (c.d[0]>1) && (c.d[c.d[0]]==0) )
        --c.d[0];
    return c;
}
BigNumber operator - (const BigNumber &a,const BigNumber &b){
    BigNumber c;
    c.d[0]=a.d[0];
    int i,x=0;
    for(i=1;i<=c.d[0];i++){
        x=10000+a.d[i]-b.d[i]+x;
        c.d[i]=x%10000;
        x=x/10000-1;
    }
    while((c.d[0]>1)&&(c.d[c.d[0]]==0))--c.d[0];
    return c;
}
bool smaller(const BigNumber &a,const BigNumber &b,int delta){
    if(a.d[0]+delta!=b.d[0])return a.d[0]+delta<b.d[0];
    int i;
    for(i=a.d[0];i>0;i--)
        if(a.d[i]!=b.d[i+delta])
            return a.d[i]<b.d[i+delta];
    return true;
}
void Minus(BigNumber &a,const BigNumber &b,int delta){
    int i,x=0;
    for(int i=1;i<=a.d[0]-delta;i++){
        x=10000+a.d[i+delta]-b.d[i]+x;
        a.d[i+delta]=x%10000;
        x=x/10000-1;
    }
    while((a.d[0]>1)&&(a.d[a.d[0]]==0))a.d[0]--;
}
BigNumber operator /(const BigNumber &a,const BigNumber &b)
{
 
    BigNumber c;
    d=a;
    int i,j,temp;
    mid1[0]=b;
    for(int i=1; i<=13; i++){
        mid1[i]=mid1[i-1]*two;
    }
    for(i=a.d[0]-b.d[0]; i>=0; i--){
        temp=8192;
        for(int j=13; j>=0; j--){
            if(smaller(mid1[j],d,i)){
                Minus(d,mid1[j],i);
                c.d[i+1]+=temp;
            }
            temp/=2;
        }
    }
    c.d[0]=max(1,a.d[0]-b.d[0]+1);
    while((c.d[0]>1)&&(c.d[c.d[0]]==0))--c.d[0];
    return c;
}
 
BigNumber qpow(BigNumber a,int n){
    BigNumber ans=one;
    while(n){
        if(n&1){
            ans=ans*a;
        }
        a=a*a;
        n>>=1;
    }
    return ans;
}
BigNumber f1,f2,f3,d1,d2,d3;
void init()
{
    f1=one,f2=one+one,f3=one+one+one+one+one;
    d1=one,d2=one+one+one,d3=one+one+one+one+one+one+one;
}
void solve()
{
    int n;
    scanf("%d",&n);
    BigNumber ans=qpow(two,(n+1));
    if(n&1){
        ans=ans-one;
        ans=ans/three;
    }else{
        ans=ans-two;
        ans=ans/three;
    }
    cout<<ans.toString()<<endl;
}
int main(){
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值