您的位置:首页 > 其它

pku oj 1001 Exponentiation

2012-11-04 13:15 183 查看
#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
);
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: