pku oj 1001 Exponentiation

#include <iostream>
#include <string>
#include <map>
using namespace std;


typedef map<int, string> map_power;


//题目中0 < n <= 25
int GetMaxLessEqu(int n)
{
    if (0 == (n & (n-1))) return n;

    int ret = 1;
    while (ret < n) ret<<=1;
    return ret>>1;
}


int GetInteger(string& str)
{
    int radix = 0;

    const int pos = str.find('.');
    if (string::npos != pos)//有小数点
    {
        while ('0' == str[str.size()-1]) str.erase(str.size()-1, 1);
        str.erase(pos, 1);
        radix = str.size() - pos;
    }
    while ('0' == str[0]) str.erase(0, 1);

    return radix;
}


//C = A*B
void mul(string& C, const string& A, const string& B)
{
    int tail = A.size() + B.size()-1;

    C.resize(tail+1);
    C.assign(C.size(), 0);
    for (int i = B.length()-1; i >= 0; i--)
    {
        for (int j = A.length()-1; j >= 0; j--)
        {
            const int pos = tail - (A.length()-1-j) - (B.length()-1-i);
            const int ret = (B[i]-'0')*(A[j]-'0');
            C[pos] += ret;
            C[pos-1] += C[pos]/10;
            C[pos] %= 10;
        }
    }
    for (int i = 0; i < C.size(); i++) C[i] += '0';
    while ('0' == C[0]) C.erase(0, 1);
}


void output(string& str, int radix, int n)
{
    if (radix > 0)
    {
        int i;
        radix *= n;
        int diff = (int)str.size() - radix;
        if (diff > 0)
        {
            for (i = 0; i < str.size()-radix; i++) cout<<str[i];
            cout<<'.';
            for (; i < str.size(); i++) cout<<str[i];
        }
        else
        {
            cout<<'.';
            for (i = 0; i < radix-str.size(); i++) cout<<'0';
            for (i = 0; i < str.size(); i++) cout<<str[i];
        }
    }
    else cout<<str;
    cout<<endl;
}


int main()
{
    int n;
    string r;

    while (cin>>r>>n)
    {
        const int nBackup = n;
        string digit = r;
        int radix = GetInteger(digit);
        int maxLessEqu = GetMaxLessEqu(n);
        map_power powVal;
        powVal[1] = digit;
        string cur = digit, ret = digit;
        for (int i = 2; i <= maxLessEqu; i*=2) 
        {
            mul(ret, cur, cur);
            powVal[i] = cur = ret;
        }
        if (maxLessEqu != n)
        {
            cur = powVal[maxLessEqu];
            while (0 != n)
            {
                n -= maxLessEqu;
                if (0 == (n & (n-1)))//n为2的幂
                {
                    mul(ret, cur, powVal[n]);
                    break;
                }
                else
                {
                    mul(ret, cur, powVal[maxLessEqu/=2]);
                    cur = ret;
                }
            }
        }
        output(ret, radix, nBackup);
    }

    return 0;
}
        我主要的思路是先把输入的浮点数转成整形,并记下小数点的位置。mul函数用来计算两个整数的乘积,最后输出的时候再添加上小数点。这个题目是计算幂,比如x^n,普通方法是连续乘积n-1次,这里我采取的办法是n = 2^x1 + 2^x2 + ... + 2x^m。比如17 = 16 + 1,23 = 16 + 4 + 2 + 1。这样可以少做几次乘法。刚开始做OJ,水平和技巧还有待提高。代码有点长,但是逻辑上会清楚点。路漫漫其修远兮。
    另外遇到的一个问题值得mark一下,我之前写了这么一句其中
if (str.size() - radix > 0){...}
    其中str为string类型,radix为int类型,str.size()为73,radix为80。结果能走进 if 里面,我好奇怪啊,都怀疑是不是编译器出错了。试了好半天,联想到编译时的"warning C4018: “<”: 有符号/无符号不匹配"。突然想到了,str.size()为size_t类型,radix为int类型,两者相减后的类型是较高的size_t,-7也就转成了size_t类型,成了正数,也就走进 if 了。
    今天(12-11-06)看到三星笔试题里有一道,和我上面说的那个问题一个意思,只不过上面那个应该更隐晦一点。
void foo(void) 
{ 
    unsigned int a = 6; 
    int b = -20; 
    (a+b > 6)  ? puts("> 6") : puts("<= 6"); 
} 
    输出是> 6
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值