ZOJ 2529 - A+B in Hogwarts 解题报告

          题目2529:A+B in Hogwarts

          链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1535

          题目描述:哈利波特去的魔法学院使用一种特殊进制法表示数字:第i位用第i个素数为进制(radix),例如“个位”的进制为第一个素数2,“十位”的进制为第二个素数3,“百位”的进制为第三个素数5,...依此类推。例如,十进制数2表示为10,十进制数6被表示为100。现在要求你为哈利波特写一个简单的计算器用于计算a+b的结果,每一行输入魔法学院的数字a和b,两个数字用空格分割,数字的每一位用逗号分割,要求计算出a+b的结果,并用魔法学院的表示法表示(注意,输入数字最多不超过25位)。

          示范输入:

          1,0 2,1
          4,2,0 1,2,0
          1 10,6,4,2,1

          示范输出:

          1,0,1
          1,1,1,0
          1,0,0,0,0,0

          该题目的难度不大,但对输入的解析和正确输出上有一定的技巧性,因此不能算特别简单的题。看到该题目的第一印象,我想把输入的数字a和b都转换为常规的int整数,然后再把a+b的结果转换为该特殊进制,但是这个转换过程会比常规的进制转换复杂一些,例如把1,0,0转换为10进制的过程是1*(2*3)+0*(2)+0=6;

          因此我们马上改变思路,采用类似大数算法的方法,即使用一个数组来表示数字,然后把每一位使用的进制存储到一个数组r中,即r中存储前25个素数。然后计算a+b的过程和大数加法完全一致,唯一不同的是,大数加法的每一位都使用10进制,而这里每一位使用的进制都不同。

          我们首先写出前25个素数,并存储到一个固定的数组中,我们可以用下面的代码来获取(请注意下面的代码完全是辅助性质,和最终题目的解并无关系):

Code_求出前25个素数
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* 判断一个数字n是否是素数 */
int isPrime(int n)
{
    int i;
    for( i=2; i < min( sqrt(n)+1, n-1) ; i++ )
    {
        if(n%i==0)
            return 0;
    }
    return 1;
}

void main()
{
    int n=1, count=0;
    printf("\n");
    for( ; count <= 30; n++)
    {
        if(isPrime(n))
        {
            printf("%3d,",n);
            count++;
            if(count%10==0)
                printf("\n");
        }
    }
}

          下面我们给出ZOJ 2529题目的完整代码:

Code_ZOJ_2529_Solution
/* ZOJ 2529 - A+B in Hogwarts */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 前25个质数,也是第i位的radix */
int r[]={2,3,5,7,11, 13,17,19,23,29, 31,37,41,43,47, 53,59,61,67,71, 73,79,83,89,97, 101,103,107,109,113};
/* 记a+b=c */
int a[30], b[30], c[30];
/*用于读入两个加数的缓冲区*/
char buf1[512], buf2[512];

/*根据输入的用逗号间隔的字符串,转化为魔法世界进制的数组表示*/
void ParseInput(char* buffer, int dest[])
{
    int i=0;/*第i位*/
    char *s;/*逗号所在的位置,从字符串的尾部向前查找*/
    while( (s=strrchr(buffer,','))!=NULL )
    {
        *s=0;/*在逗号处截断字符串!*/
        dest[i++] = atoi(s+1);
    }
    /*已经没有逗号了,还剩下最高位的数字*/
    dest[i++] = atoi(buffer);
}

/*计算出c=a+b*/
void Add()
{
    int i;
    for(i=0;i<30;i++)
        c[i]=a[i]+b[i];
    /*进位*/
    for(i=0;i<29;i++)
    {
        c[i+1]+=c[i]/r[i];
        c[i]=c[i]%r[i];
    }    
}

/*把结果打印出来,包含换行符,注意特殊情况,比如结果为1和0时*/
void PrintResult()
{
    int i=29;
    while(c[i]==0) i--;
    for(;i>0;i--) printf("%d,", c[i]);
    /*打印最后一位*/
    printf("%d\n", c[0]);
}

int main()
{
    while(scanf("%s %s",buf1,buf2)!=EOF && strcmp(buf1,"end")!=0)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        ParseInput(buf1, a);
        ParseInput(buf2, b);
        Add();
        PrintResult();
    }
    return 0;
}

 

          最后值得一提的是,解析输入的代码:ParseInput方法,用于把形如"10,6,4,2,0"这样的字符串解释到一个int数组(dest)内,是dest数组成为{0,2,4,6,10,0,...}。

          用于把结果输入的方法,PrintResult,要注意当计算结果为0和1这样的比较特殊的情况,必须也应该能正确输出。这些比较临界的细节是尤其需要注意的地方。

时间: 2024-10-08 12:05:11

ZOJ 2529 - A+B in Hogwarts 解题报告的相关文章

ZOJ 1009, 1115, 1476, 1733, 2405 解题报告

        星期天这天一口气AC了五道题,除了1009外基本都可算是简单题.        (1)1009 Enigma:        http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009        题目是讲解二战期间德国使用的密码机Enigma.明文通过按键,通过转盘(rotor)转换为密文.如下图所示为有1个转盘,一共有6个字母的情况,每击键一次,转盘转动一格.如果含有多个转盘,则以类似数字进制方式转动,

杭电ACM 2000-&amp;gt;2099 100道题 详细解题报告出炉

我去年暑假花了5天,把杭电ACM网站上2000到2099这100道题全AC了,又花了10来天精心写解题报告.里面包括题目.解题思路.编程技巧以及参考源码.所有代码都是使用C/C++写的. 最近整理资料时无意间发现,打包成chm文件和大家分享.我已经上传到CSDN上了.下载地址:http://download.csdn.net/source/492194 也可到我的Google Sites上下载. 题号 题名 题号 题名 2000 ASCII码排序 2001 计算两点间的距离 2002 计算球体积

ZOJ 1111 - Poker Hands 解题报告

          Poker Hands (比较两手牌的大小)           http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=111           题目描述:这道题要求比较两手牌的大小.每手牌都有5张牌组成,牌的大小的定义如下,首先确定这组牌的所属种类是下面哪一种(若同属同一种类,则根据该分类后面的比较规则继续比较,所属种类越靠后牌越大).           ● High Card:杂牌(不属于下面任何一种).

ZOJ - 1098 Simple Computer 解题报告

Simple Computers Time Limit: 1 Second      Memory Limit: 32768 KB You are to write an interpreter for a simple computer. This computer uses a processor with a small number of machine instructions. Furthermore, it is equipped with 32 byte of memory, o

ZOJ 3505. Yet Another Set of Numbers 解题报告

ZOJ 3505:Yet Another Set of Numbers 地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3505   题意:有一个数字集合,集合中的数遵循以下规则:   ( 1 ). 每个数字的最高位不是 0 ; ( 2 ). 每个数字包含最多 N 位,且只有 0,1,2,3 这四个数字可能出现(0 < N < 20); ( 3 ). 每个数字的相邻位不同(例如:301是有效的,300不是); (

ZOJ 1010. Area 解题报告

ZOJ 1010. Area. 题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1010 基本题意:此题目给出 n 个点的坐标 (xi,yi ) ,要求求出这些点按顺序围成的多边形的面积.同时要求检测出不合法的多边形(例如非相邻边彼此相交的情况).     此题求面积不难,样例很容易就过了,但是提交 10+ 次基本都是 WA ,几乎失去信心.做题最郁闷的就是你不知道问题到底出在什么地方,可能改了很多次都没有试对地

ZOJ 1205 - Martian Addition 解题报告

          http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1205           题目说明:(把题目从GOOGLE翻译的结果修改而来)           在22世纪,科学家们发现智能居民生活在火星.火星人非常喜欢数学.每一年,他们将举行一次火星算术大赛(计算机) ,竞赛内容是计算两个100位数的和,使用时间最少的人获得冠军.今年,他们还邀请地球上的人参加竞赛.            作为唯一代表地球,你发

ZOJ 1635 - Directory Listing 解题报告

       题目:1635 Directory Listing(列出目录)        http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=635         看描述好像是chenyue姐姐出的题目.这道题的大意是,给出一个UNIX文件系统的树,以及树节点的自身size,按要求列出它们,保持适当的缩进,并统计每个节点的总的size.输入的第一行代表根结点,每一个节点由name size或者*name size的形式组成(如

ZOJ 1090 - The Circumference of the Circle 解题报告

      题目的链接在这里:       http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1090       题目描述很简单,大意是,给出三个点的坐标,设为A(x1,y1),B (x2, y2),C (x3, y3),然后求出通过这三点的圆的周长(保留两位小数).但推导公式却比较麻烦,我是这样来做的.       首先根据同一个弦的圆心角角度相同,不难得出,圆周的直径d= BC/ sin a = AC/ sin b =