最近两次acm培训赛都遇到了类似题目,其实这类题目的共同做法是通过字符数组或字符串模拟操作,再加上我之前做在线Office之类的东西时没少和字符串打交道,所以就总结出几点小经验来,拿出来分享。
另外我的个人博客开通,主要会写一些技术性文章,地址 http://blog.sunfangweb.cn , 如果这个地址访问不了可以用 www.rtswhp.org.cn/blog/?usrt=sfccni 来访问。本文章在博客同步发表。
言归正传,首先看看字符串的拆分,这是很重要的一点,重点在于判断好分隔的符号与分隔后各块的存储方式。以在线Office中的例子为例,把一串类似“A87D8-8988-EEFF76-2331-ADDF6G,23133323,976556,223441,25256741.......”等的字符串分开,使“23133323”类似的项存在数组里,一下是代码:
//ActionScript3代码:
var tempstr:String=xnshareserv.lastResult.friends_getAppUsers_response.uid+".";
//在字符串皆为加入符号,作为循环终止的判断,注意应该加入原本不可能出现的符号
var tempstr2:String="";
var i:int=0,j:int=0,k:int=0;
var count:int=1; //计数器1,用于做数组下标
Debug.inspect(xnshareserv.lastResult);
while(tempstr.charAt(i)!=".") {//判断结束
while(tempstr.charCodeAt(i)!=44) {//判断“,”分隔符
//Debug.trace("i:"+i);
//Debug.trace("char:"+tempstr.charAt(i));
tempstr2=tempstr2.concat(tempstr.charAt(i));//将两个","间字符遍历复制
i++;
if(tempstr.charAt(i)==".") break;
}
if(tempstr.charAt(i)==".") break;
//Debug.trace("tempstr2:"+tempstr2);
if(count==1) {
; //头一个段不加
}else{
temparr.push(tempstr2); //加入每段数据到数组
}
tempstr2=""; //清空临时的数据段
i++;
count++;
}
案例二,大数加法,实质是用字符数组人工模拟加法。
题目要求是进行1000位数以内的加法,显然超long long int的范围了......
//C代码:
//大数加法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char res[1001]={'0'}; //结果集
char na[1001]={'0'}; //运算的a
char nb[1001]={'0'}; //运算的b
char ia[1001]={'0'}; //输入的a与b,要在处理后变成na,nb
char ib[1001]={'0'};
void cplus(char * a,char * b) { //进行大数相加
int la,lb=0;
int i=0;
int rest=0; //临时变量,用于进行每位的存放
for(i=0;i<1001;i++) {
rest=((int)(*(a-i)-48)+(int)(*(b-i)-48)); //每位的加法,注意减去48的"0"的ascii码
if(rest>=10){
rest-=10; //进位处理
res[1000-i-1]+=1;
}
res[1000-i]+=rest;
}
}
void prep() { //准备函数,把ia,ib搞成na,nb,区别是处理时向数组尾对齐
int i=0;
while (strlen(ia)-i!=0)
{
na[1000-i]=ia[strlen(ia)-i-1];
i++;
}
i=0;
while (strlen(ib)-i!=0)
{
nb[1000-i]=ib[strlen(ib)-i-1];
i++;
}
}
void print() { //输出结果
int i=0,j=0;
while (res[i]=='0')
{
i++;
}
while (i+j<1001)
{
printf("%c",res[i+j]);
j++;
}
}
int main() {
memset(res,'0',1001);
memset(na,'0',1001);
memset(nb,'0',1001);
memset(ia,'0',1001);
memset(ib,'0',1001);
scanf("%s %s",ia,ib);
prep();
cplus(&na[1000],&nb[1000]);
print();
system("PAUSE");
return 0;
}
案例三:高精度乘方。
//C++代码:
//B题:求幂
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std;
void multiply(string & a, string & b);
string powit(string & number,int n);
int main()
{
string number;
int n;
while (cin>>number>>n){
cout << powit(number,n) << endl;
}
//system("pause");
return 0;
}
void multiply(string & a, string & b)
{
int i=0,j=0,k=0;
string result;
result.resize(a.length() + b.length());
for (i=0;i<result.length();i++)
result[i]=0; //result存储时是从结果的最低位存储的,进位就可以往后进了
for (i = 0; i < a.length(); i++ )
{
for (j = 0, k = 0; j < b.length(); j++ )
{
int l = (int)(a[ a.length() - i - 1 ]-'0') * int(b[b.length()- j - 1]-'0') + k;
result[i+j] += l;
k = result[i+j] / 10;
result[i+j] = result[i+j] % 10;
}
if(k!=0) result[i+j] = k; // 进位处理
}
a.clear(); //清空,用来处理下边的东东
for(i = result.length()-1; i>0 && result[i] == 0; i-- )
result.erase(i, 1);
for (i = 1; i <= result.length(); i++ )
a.push_back(result[result.length()-i] + '0');
}
string powit(string & number,int n) {
int i, posi = 0;
for (i = 0; i < number.length(); ++i )
if (number[i] == '.')
break;
posi = number.length() - i - 1;
number.erase(i, 1);
string result2("1");
for (i = 0; i < n; ++i)
multiply(result2, number);
if (posi != -1)
posi *= n; //小数点的判断
while ( (int)result2.length() < posi )
result2.insert(result2.begin(), '0');
if (posi != -1)
{
result2.insert(result2.end() - posi, '.');
for (i = result2.length() - 1; i > 1 && result2[i] == '0'; i-- ) ;
result2.erase(i + 1);
if (result2[i] == '.') result2.erase(i); //干掉多余的0
}
return result2;
}