upc 6760 九连环(大数)

题目描述

九连环是一种源于中国的传统智力游戏。如图所示,九个圆环套在一把“剑”上,并且互相牵连。游戏的目标是把九个圆环从“剑”上卸下。
圆环的装卸需要遵守两个规则。
第一个(最右边)环任何时候都可以装上或卸下。
如果第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

题解:题目本身不难,奈何不知道大数

 ***大数问题,其实就是模拟运算,因为系统自带的int long bouble这些类型无法容纳百位千位的大数字,从而手动模拟运算过程,使用字符串来表示这样的超大数字,如果你会Java的话就简单多了,直接有一个大数类,可以像用函数一样直接调用***

自己写的代码略low,贴一个大佬的代码作参考:
自己的:

#include<bits/stdc++.h>
#define LL long long
#define inf 0x3f3f3f3
using namespace std;
typedef long long ll;
const int N = 1e7+7;
const long long mod=1e9;
typedef long long ll;
const int base = 100000000; //进制
const int base_digits = 8; //进制位数
struct bigint {
    vector<int> z;
    int sign;  //1 for +,-1 for -
    bigint(){sign=1;}
    bigint(ll v){*this=v;z.push_back(0);}
    bigint(const string &s){read(s);}
    void operator=(const bigint &v){
        sign = v.sign;
        z = v.z;
    }
    void operator=(ll v){
        sign = 1;
        if (v < 0)
            sign = -1, v = -v;
        z.clear();
        for (; v > 0; v = v / base)
            z.push_back(v % base);
    }
    void trim() {
        while (!z.empty() && z.back() == 0)
            z.pop_back();
        if (z.empty())
            sign = 1;
    }
    bigint operator-() const {
        bigint res = *this;
        res.sign = -sign;
        return res;
    }
    bigint abs() const {
        bigint res = *this;
        res.sign *= res.sign;
        return res;
    }
    void read(const string &s){
        sign = 1;
        z.clear();
        int pos = 0;
        while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-')
                sign = -sign;
            ++pos;
        }
        for (int i = s.size() - 1; i >= pos; i -= base_digits) {
            int x = 0;
            for (int j = max(pos, i - base_digits + 1); j <= i; j++)
                x = x * 10 + s[j] - '0';
            z.push_back(x);
        }
        trim();
    }
    bigint operator+(const bigint &v) const {
        if (sign == v.sign) {
            bigint res = v;
            for (int i = 0, carry = 0; i < (int) max(z.size(), v.z.size()) || carry; ++i) {
                if (i == (int) res.z.size())
                    res.z.push_back(0);
                res.z[i] += carry + (i < (int) z.size() ? z[i] : 0);
                carry = res.z[i] >= base;
                if (carry)
                    res.z[i] -= base;
            }
            return res;
        }
        return *this - (-v);
    }
    bigint operator-(const bigint &v) const {
        if (sign == v.sign) {
            if (abs() >= v.abs()) {
                bigint res = *this;
                for (int i = 0, carry = 0; i < (int) v.z.size() || carry; ++i) {
                    res.z[i] -= carry + (i < (int) v.z.size() ? v.z[i] : 0);
                    carry = res.z[i] < 0;
                    if (carry)
                        res.z[i] += base;
                }
                res.trim();
                return res;
            }
            return -(v - *this);
        }
        return *this + (-v);
    }
    typedef vector<long long> vll;
    static vll karatsubaMultiply(const vll &a, const vll &b) {
        int n = a.size();
        vll res(n + n);
        if (n <= 32) {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    res[i + j] += a[i] * b[j];
            return res;
        }
        int k = n >> 1;
        vll a1(a.begin(), a.begin() + k);
        vll a2(a.begin() + k, a.end());
        vll b1(b.begin(), b.begin() + k);
        vll b2(b.begin() + k, b.end());
        vll a1b1 = karatsubaMultiply(a1, b1);
        vll a2b2 = karatsubaMultiply(a2, b2);
        for (int i = 0; i < k; i++)
            a2[i] += a1[i];
        for (int i = 0; i < k; i++)
            b2[i] += b1[i];
        vll r = karatsubaMultiply(a2, b2);
        for (int i = 0; i < (int) a1b1.size(); i++)
            r[i] -= a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            r[i] -= a2b2[i];
        for (int i = 0; i < (int) r.size(); i++)
            res[i + k] += r[i];
        for (int i = 0; i < (int) a1b1.size(); i++)
            res[i] += a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            res[i + n] += a2b2[i];
        return res;
    }
    bigint operator*(const bigint &v) const {
        vll a(this->z.begin(), this->z.end());
        vll b(v.z.begin(), v.z.end());
        while (a.size() < b.size())
            a.push_back(0);
        while (b.size() < a.size())
            b.push_back(0);
        while (a.size() & (a.size() - 1))
            a.push_back(0), b.push_back(0);
        vll c = karatsubaMultiply(a, b);
        bigint res;
        res.sign = sign * v.sign;
        for (int i = 0, carry = 0; i < (int) c.size(); i++) {
            long long cur = c[i] + carry;
            res.z.push_back((int) (cur % base));
            carry = (int) (cur / base);
        }
        res.trim();
        return res;
    }
    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1){
        int norm = base / (b1.z.back() + 1);
        bigint a = a1.abs() * norm;
        bigint b = b1.abs() * norm;
        bigint q, r;
        q.z.resize(a.z.size());
        for (int i = a.z.size() - 1; i >= 0; i--) {
            r *= base;
            r += a.z[i];
            int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0;
            int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0;
            int d = ((long long) s1 * base + s2) / b.z.back();
            r -= b * d;
            while (r < 0)
                r += b, --d;
            q.z[i] = d;
        }
        q.sign = a1.sign * b1.sign;
        r.sign = a1.sign;
        q.trim();
        r.trim();
        return make_pair(q, r / norm);
    }
    bigint operator/(const bigint &v) const{
        return divmod(*this, v).first;
    }
    bigint operator%(const bigint &v) const {
        return divmod(*this, v).second;
    }
    void operator+=(const bigint &v) {
        *this = *this + v;
    }
    void operator-=(const bigint &v) {
        *this = *this - v;
    }
    void operator*=(const bigint &v) {
        *this = *this * v;
    }
    void operator/=(const bigint &v) {
        *this = *this / v;
    }
    bool operator<(const bigint &v) const {
        if (sign != v.sign)
            return sign < v.sign;
        if (z.size() != v.z.size())
            return z.size() * sign < v.z.size() * v.sign;
        for (int i = z.size() - 1; i >= 0; i--)
            if (z[i] != v.z[i])
                return z[i] * sign < v.z[i] * sign;
        return false;
    }
    bool operator>(const bigint &v) const {
        return v < *this;
    }
    bool operator<=(const bigint &v) const {
        return !(v < *this);
    }
    bool operator>=(const bigint &v) const {
        return !(*this < v);
    }
    bool operator==(const bigint &v) const {
        return !(*this < v) && !(v < *this);
    }
    bool operator!=(const bigint &v) const {
        return *this < v || v < *this;
    }
    friend istream& operator>>(istream &stream, bigint &v) {
        string s;
        stream >> s;
        v.read(s);
        return stream;
    }
    friend ostream& operator<<(ostream &stream, const bigint &v) {
        if (v.sign == -1)
            stream << '-';
        stream << (v.z.empty() ? 0 : v.z.back());
        for (int i = (int) v.z.size() - 2; i >= 0; --i)
            stream << setw(base_digits) << setfill('0') << v.z[i];
        return stream;
    }
    void operator*=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = 0, carry = 0; i < (int) z.size() || carry; ++i) {
            if (i == (int) z.size())
                z.push_back(0);
            long long cur = z[i] * (long long) v + carry;
            carry = (int) (cur / base);
            z[i] = (int) (cur % base);
        }
        trim();
    }
    bigint operator*(int v) const {
        bigint res = *this;
        res *= v;
        return res;
    }
    void operator/=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = (int) z.size() - 1, rem = 0; i >= 0; --i) {
            long long cur = z[i] + rem * (long long) base;
            z[i] = (int) (cur / v);
            rem = (int) (cur % v);
        }
        trim();
    }
    bigint operator/(int v) const {
        bigint res = *this;
        res /= v;
        return res;
    }
    int operator%(int v) const {
        if (v < 0)
            v = -v;
        int m = 0;
        for (int i = z.size() - 1; i >= 0; --i)
            m = (z[i] + m * (long long) base) % v;
        return m * sign;
    }
    friend bigint sqrt(const bigint &a1) {
        bigint a = a1;
        while (a.z.empty() || a.z.size() % 2 == 1)
            a.z.push_back(0);
        int n = a.z.size();
        int firstDigit = (int) sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
        int norm = base / (firstDigit + 1);
        a *= norm;
        a *= norm;
        while (a.z.empty() || a.z.size() % 2 == 1)
            a.z.push_back(0);
        bigint r = (long long) a.z[n - 1] * base + a.z[n - 2];
        firstDigit = (int) sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
        int q = firstDigit;
        bigint res;
        for(int j = n / 2 - 1; j >= 0; j--) {
            for(; ; --q) {
                bigint r1 = (r - (res * 2 * base + q) * q) * base * base + (j > 0 ? (long long) a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0);
                if (r1 >= 0) {
                    r = r1;
                    break;
                }
            }
            res *= base;
            res += q;
            if (j > 0) {
                int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0;
                int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0;
                int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0;
                q = ((long long) d1 * base * base + (long long) d2 * base + d3) / (firstDigit * 2);
            }
        }
        res.trim();
        return res / norm;
    }


    };

bigint qpow(ll n, ll m)
{  bigint ans=1;
    //n%=mod;

    while(m)
    {
        if(m%2)
            ans=(ans*n);
        m/=2;
        n=(n*n);
    }
    cout<<"aaa"<<ans-1<<endl;
    return ans;
}
bigint qpow(int b)
{
    bigint ans=1,a=2;
    while(b)
    {
        if(b&1)
            ans=(ans*a);
        a=(a*a);
        b/=2;
    }
    //cout<<"aaa"<<ans/3<<endl;
    return ans;
}


int main()
{
    int n,m;
    scanf("%d",&m);
    while(m--){
            scanf("%d",&n);

    if(n%2==1)
       cout<<((qpow(n+1))/3)<<endl;
    else
       cout<<((qpow(n+1))/3)<<endl;

    }
    return 0;
}

大佬的:

#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;
}

还有一个java版本的:

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]));
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值