CCF NOI1154 大整数开方

来源:互联网 发布:淘宝怎么入驻商家 编辑:程序博客网 时间:2024/06/05 13:17

问题链接CCF NOI1154 大整数开方


时间限制: 1000 ms  空间限制: 262144 KB

题目描述 

  输入一个正整数n(1<=n<=10^100),输出n的平方根的整数部分。

输入

  正整数n。

输出

  n的平方根的整数部分。

样例输入

10
样例输出

3

数据范围限制

  1<=n<=10^100




问题分析

  这个大整数开方问题需要两样东西,一是大数计算类(找到一个可以用的),二是整数开方算法。这两者一结合,问题就解决了。

程序说明

  这里给出来整数开方算法程序,可以根据这个程序实现大数的开方计算。

  有了大数计算类,实际需要编写的代码就很少了。

要点详解

  • 算法很重要



参考链接

B00008 C++实现的大整数计算(一)
Vijos P1786 质因数分解 

关键代码,计算整数开方算法:

// 计算整数开方函数  long sqrt(long n)  {      long a, b, m;      a = 1;      b = n;      for(;;) {          m = (a + b) / 2;          if (m == a || m == b)              return m;          if (m * m > n)              b = m;          else              a = m;      }  }  

100分通过的C++程序:

#include <iostream>#include <string>#include <sstream>#include <cmath>using namespace std;/* * @author panks * Big Integer library in C++, single file implementation. */#define MAX 10000 // for stringsusing namespace std;class BigInteger {private:    string number;    bool sign;public:    BigInteger(); // empty constructor initializes zero    BigInteger(string s); // "string" constructor    BigInteger(string s, bool sin); // "string" constructor    BigInteger(int n); // "int" constructor    void setNumber(string s);    const string& getNumber(); // retrieves the number    void setSign(bool s);    const bool& getSign();    BigInteger absolute(); // returns the absolute value    void operator = (BigInteger b);    bool operator == (BigInteger b);    bool operator != (BigInteger b);    bool operator > (BigInteger b);    bool operator < (BigInteger b);    bool operator >= (BigInteger b);    bool operator <= (BigInteger b);    BigInteger& operator ++(); // prefix    BigInteger  operator ++(int); // postfix    BigInteger& operator --(); // prefix    BigInteger  operator --(int); // postfix    BigInteger operator + (BigInteger b);    BigInteger operator - (BigInteger b);    BigInteger operator * (BigInteger b);    BigInteger operator / (BigInteger b);    BigInteger operator % (BigInteger b);    BigInteger& operator += (BigInteger b);    BigInteger& operator -= (BigInteger b);    BigInteger& operator *= (BigInteger b);    BigInteger& operator /= (BigInteger b);    BigInteger& operator %= (BigInteger b);    BigInteger& operator [] (int n);    BigInteger operator -(); // unary minus sign    operator string(); // for conversion from BigInteger to stringprivate:    bool equals(BigInteger n1, BigInteger n2);    bool less(BigInteger n1, BigInteger n2);    bool greater(BigInteger n1, BigInteger n2);    string add(string number1, string number2);    string subtract(string number1, string number2);    string multiply(string n1, string n2);    pair<string, long long> divide(string n, long long den);    string toString(long long n);    long long toInt(string s);};//------------------------------------------------------------------------------BigInteger::BigInteger() { // empty constructor initializes zero    number = "0";    sign = false;}BigInteger::BigInteger(string s) { // "string" constructor    if( isdigit(s[0]) ) { // if not signed        setNumber(s);        sign = false; // +ve    } else {        setNumber( s.substr(1) );        sign = (s[0] == '-');    }}BigInteger::BigInteger(string s, bool sin) { // "string" constructor    setNumber( s );    setSign( sin );}BigInteger::BigInteger(int n) { // "int" constructor    stringstream ss;    string s;    ss << n;    ss >> s;    if( isdigit(s[0]) ) { // if not signed        setNumber( s );        setSign( false ); // +ve    } else {        setNumber( s.substr(1) );        setSign( s[0] == '-' );    }}void BigInteger::setNumber(string s) {    number = s;}const string& BigInteger::getNumber() { // retrieves the number    return number;}void BigInteger::setSign(bool s) {    sign = s;}const bool& BigInteger::getSign() {    return sign;}BigInteger BigInteger::absolute() {    return BigInteger( getNumber() ); // +ve by default}void BigInteger::operator = (BigInteger b) {    setNumber( b.getNumber() );    setSign( b.getSign() );}bool BigInteger::operator == (BigInteger b) {    return equals((*this) , b);}bool BigInteger::operator != (BigInteger b) {    return ! equals((*this) , b);}bool BigInteger::operator > (BigInteger b) {    return greater((*this) , b);}bool BigInteger::operator < (BigInteger b) {    return less((*this) , b);}bool BigInteger::operator >= (BigInteger b) {    return equals((*this) , b)           || greater((*this), b);}bool BigInteger::operator <= (BigInteger b) {    return equals((*this) , b)           || less((*this) , b);}BigInteger& BigInteger::operator ++() { // prefix    (*this) = (*this) + 1;    return (*this);}BigInteger BigInteger::operator ++(int) { // postfix    BigInteger before = (*this);    (*this) = (*this) + 1;    return before;}BigInteger& BigInteger::operator --() { // prefix    (*this) = (*this) - 1;    return (*this);}BigInteger BigInteger::operator --(int) { // postfix    BigInteger before = (*this);    (*this) = (*this) - 1;    return before;}BigInteger BigInteger::operator + (BigInteger b) {    BigInteger addition;    if( getSign() == b.getSign() ) { // both +ve or -ve        addition.setNumber( add(getNumber(), b.getNumber() ) );        addition.setSign( getSign() );    } else { // sign different        if( absolute() > b.absolute() ) {            addition.setNumber( subtract(getNumber(), b.getNumber() ) );            addition.setSign( getSign() );        } else {            addition.setNumber( subtract(b.getNumber(), getNumber() ) );            addition.setSign( b.getSign() );        }    }    if(addition.getNumber() == "0") // avoid (-0) problem        addition.setSign(false);    return addition;}BigInteger BigInteger::operator - (BigInteger b) {    b.setSign( ! b.getSign() ); // x - y = x + (-y)    return (*this) + b;}BigInteger BigInteger::operator * (BigInteger b) {    BigInteger mul;    mul.setNumber( multiply(getNumber(), b.getNumber() ) );    mul.setSign( getSign() != b.getSign() );    if(mul.getNumber() == "0") // avoid (-0) problem        mul.setSign(false);    return mul;}// Warning: Denomerator must be within "long long" size not "BigInteger"BigInteger BigInteger::operator / (BigInteger b) {    long long den = toInt( b.getNumber() );    BigInteger div;    div.setNumber( divide(getNumber(), den).first );    div.setSign( getSign() != b.getSign() );    if(div.getNumber() == "0") // avoid (-0) problem        div.setSign(false);    return div;}// Warning: Denomerator must be within "long long" size not "BigInteger"BigInteger BigInteger::operator % (BigInteger b) {    long long den = toInt( b.getNumber() );    BigInteger rem;    long long rem_int = divide(number, den).second;    rem.setNumber( toString(rem_int) );    rem.setSign( getSign() != b.getSign() );    if(rem.getNumber() == "0") // avoid (-0) problem        rem.setSign(false);    return rem;}BigInteger& BigInteger::operator += (BigInteger b) {    (*this) = (*this) + b;    return (*this);}BigInteger& BigInteger::operator -= (BigInteger b) {    (*this) = (*this) - b;    return (*this);}BigInteger& BigInteger::operator *= (BigInteger b) {    (*this) = (*this) * b;    return (*this);}BigInteger& BigInteger::operator /= (BigInteger b) {    (*this) = (*this) / b;    return (*this);}BigInteger& BigInteger::operator %= (BigInteger b) {    (*this) = (*this) % b;    return (*this);}BigInteger& BigInteger::operator [] (int n) {    return *(this + (n*sizeof(BigInteger)));}BigInteger BigInteger::operator -() { // unary minus sign    return (*this) * -1;}BigInteger::operator string() { // for conversion from BigInteger to string    string signedString = ( getSign() ) ? "-" : ""; // if +ve, don't print + sign    signedString += number;    return signedString;}bool BigInteger::equals(BigInteger n1, BigInteger n2) {    return n1.getNumber() == n2.getNumber()           && n1.getSign() == n2.getSign();}bool BigInteger::less(BigInteger n1, BigInteger n2) {    bool sign1 = n1.getSign();    bool sign2 = n2.getSign();    if(sign1 && ! sign2) // if n1 is -ve and n2 is +ve        return true;    else if(! sign1 && sign2)        return false;    else if(! sign1) { // both +ve        if(n1.getNumber().length() < n2.getNumber().length() )            return true;        if(n1.getNumber().length() > n2.getNumber().length() )            return false;        return n1.getNumber() < n2.getNumber();    } else { // both -ve        if(n1.getNumber().length() > n2.getNumber().length())            return true;        if(n1.getNumber().length() < n2.getNumber().length())            return false;        return n1.getNumber().compare( n2.getNumber() ) > 0; // greater with -ve sign is LESS    }}bool BigInteger::greater(BigInteger n1, BigInteger n2) {    return ! equals(n1, n2) && ! less(n1, n2);}string BigInteger::add(string number1, string number2) {    string add = (number1.length() > number2.length()) ?  number1 : number2;    char carry = '0';    int differenceInLength = abs( (int) (number1.size() - number2.size()) );    if(number1.size() > number2.size())        number2.insert(0, differenceInLength, '0'); // put zeros from left    else// if(number1.size() < number2.size())        number1.insert(0, differenceInLength, '0');    for(int i=number1.size()-1; i>=0; --i) {        add[i] = ((carry-'0')+(number1[i]-'0')+(number2[i]-'0')) + '0';        if(i != 0) {            if(add[i] > '9') {                add[i] -= 10;                carry = '1';            } else                carry = '0';        }    }    if(add[0] > '9') {        add[0]-= 10;        add.insert(0,1,'1');    }    return add;}string BigInteger::subtract(string number1, string number2) {    string sub = (number1.length()>number2.length())? number1 : number2;    int differenceInLength = abs( (int)(number1.size() - number2.size()) );    if(number1.size() > number2.size())        number2.insert(0, differenceInLength, '0');    else        number1.insert(0, differenceInLength, '0');    for(int i=number1.length()-1; i>=0; --i) {        if(number1[i] < number2[i]) {            number1[i] += 10;            number1[i-1]--;        }        sub[i] = ((number1[i]-'0')-(number2[i]-'0')) + '0';    }    while(sub[0]=='0' && sub.length()!=1) // erase leading zeros        sub.erase(0,1);    return sub;}string BigInteger::multiply(string n1, string n2) {    if(n1.length() > n2.length())        n1.swap(n2);    string res = "0";    for(int i=n1.length()-1; i>=0; --i) {        string temp = n2;        int currentDigit = n1[i]-'0';        int carry = 0;        for(int j=temp.length()-1; j>=0; --j) {            temp[j] = ((temp[j]-'0') * currentDigit) + carry;            if(temp[j] > 9) {                carry = (temp[j]/10);                temp[j] -= (carry*10);            } else                carry = 0;            temp[j] += '0'; // back to string mood        }        if(carry > 0)            temp.insert(0, 1, (carry+'0'));        temp.append((n1.length()-i-1), '0'); // as like mult by 10, 100, 1000, 10000 and so on        res = add(res, temp); // O(n)    }    while(res[0] == '0' && res.length()!=1) // erase leading zeros        res.erase(0,1);    return res;}pair<string, long long> BigInteger::divide(string n, long long den) {    long long rem = 0;    string result;    result.resize(MAX);    for(int indx=0, len = n.length(); indx<len; ++indx) {        rem = (rem * 10) + (n[indx] - '0');        result[indx] = rem / den + '0';        rem %= den;    }    result.resize( n.length() );    while( result[0] == '0' && result.length() != 1)        result.erase(0,1);    if(result.length() == 0)        result = "0";    return make_pair(result, rem);}string BigInteger::toString(long long n) {    stringstream ss;    string temp;    ss << n;    ss >> temp;    return temp;}long long BigInteger::toInt(string s) {    long long sum = 0;    for(int i=0; i<(int)s.length(); i++)        sum = (sum*10) + (s[i] - '0');    return sum;}// 计算整数开方函数void sqrt(string& n){    BigInteger a=1, b(n), m;    for(;;) {        m = a + b;        m = m / 2;        if (m == a || m == b) {            cout << m.getNumber() << endl;            break;        }        if (m * m > n)            b = m;        else            a = m;    }}int main(){    string s;    cin >> s;    sqrt(s);    return 0;}



0 0