杭电 acm 1099

来源:互联网 发布:windows桌面整理软件 编辑:程序博客网 时间:2024/05/16 09:34

多校综合排名前25名的学校请发送邮件到HDUACM@QQ.COM,告知转账信息(支付宝或者卡号)

Lottery

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2490    Accepted Submission(s): 1124


Problem Description
Eddy's company publishes a kind of lottery.This set of lottery which are numbered 1 to n, and a set of one of each is required for a prize .With one number per lottery, how many lottery on average are required to make a complete set of n coupons?
 

Input
Input consists of a sequence of lines each containing a single positive integer n, 1<=n<=22, giving the size of the set of coupons.
 

Output
For each input line, output the average number of lottery required to collect the complete set of n coupons. If the answer is an integer number, output the number. If the answer is not integer, then output the integer part of the answer followed by a space and then by the proper fraction in the format shown below. The fractional part should be irreducible. There should be no trailing spaces in any line of ouput.
 

Sample Input
2
5
17
 

Sample Output
3
5
11 --
12
34046358 ------
720720
首先,看到这道题尴尬呵呵,看不懂题意。。。

然后网上查了之后才知道是求n(1/1+1/2+1/3+......1/n)

写的过程中,发现有较大问题的是数据溢出了,超出了 int 的范围,所以用了__int64 ,然后注意到输出格式  %I64d 中的 I 必须大写。

以下是我写的AC代码,一次通过可怜好激动,因为修改了许久。

<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;"></span></span><pre name="code" class="plain"><pre name="code" class="plain">#include<stdio.h>int main(){    __int64 a,b,c,up,down,cha,UP,DOWN,CHA,i,n1,n2,size1,size2;    int n;    while(scanf("%d",&n)!=EOF){          if(n==0) printf("0\n");          if(n==1) printf("1\n");          if(n>1){             c=1;b=1;             for(i=1;i<n;i++){                 c=c*(i+1)+b;                                  b=b*(i+1);                  UP=c;                                   //UP和DOWN没什么用,只是客串一下,临时辅助约分                  DOWN=b;                 while(1){                               //更相减损术(第一次约分),能约分的先约分,防止数据溢出                        CHA=UP-DOWN;                       if(DOWN==1){                      //无公因子                           break;                       }                                               if(CHA==DOWN&&CHA!=1){            //有公因子cha                           c=c/CHA;                       //进行约分                           b=b/DOWN;                          break;                                                  }                       UP=CHA>DOWN?CHA:DOWN;             //UP取大                        DOWN=CHA<DOWN?CHA:DOWN;           //DOWN取小                  }                                                       }             if(n*c%b==0){                printf("%I64d\n",n*c/b);             }             else{                  up=c*n;                  down=b;                  while(1){                             //更相减损术(第二次约分)                         cha=up-down;                        if(down==1){                    //无公因子                            a=c/b;                           c=c*n%b;                           break;                        }                        if(cha==down&&cha!=1){          //有公因子cha                            c=c*n/cha;                           b=b/down;                           a=c/b;                           c=c%b;                           break;                                                   }                        up=cha>down?cha:down;                        down=cha<down?cha:down;                  }                   size1=size2=0;                       //size1,size2分别为整数部分的位数和分子的位数                   n1=a;                    n2=b;                   while(n1!=0){                        //获得分母位数                          size1++;                          n1/=10;                    }                   while(n2!=0){                        //获得分子位数                          size2++;                          n2/=10;                    }                                                        //按题目要求的格式打印结果                   for(i=0;i<=size1;i++) printf(" ");                       printf("%I64d\n",c);                       printf("%I64d ",a);                   for(i=0;i<size2;i++) printf("-");                       printf("\n");                   for(i=0;i<=size1;i++) printf(" ");                       printf("%I64d\n",b);             }                       }    }  }


不过这程序在本地测试时只能满足 n 到 43。

为了测试杭电的测试数据范围,修改后又再次交了,代码如下:

#include<stdio.h>int main(){    __int64 a,b,c,up,down,cha,UP,DOWN,CHA,i,n1,n2,size1,size2;    int n;    while(scanf("%d",&n)!=EOF){          if(n==0) printf("0\n");          if(n==1) printf("1\n");          if(n>1){             c=1;b=1;             for(i=1;i<n;i++){                 c=c*(i+1)+b;                                  b=b*(i+1); /*                 UP=c;                                   //UP和DOWN没什么用,只是客串一下,临时辅助约分                  DOWN=b;                 while(1){                               //更相减损术(第一次约分),能约分的先约分,防止数据溢出                        CHA=UP-DOWN;                       if(DOWN==1){                      //无公因子                           break;                       }                                               if(CHA==DOWN&&CHA!=1){            //有公因子cha                           c=c/CHA;                       //进行约分                           b=b/DOWN;                          break;                                                  }                       UP=CHA>DOWN?CHA:DOWN;             //UP取大                        DOWN=CHA<DOWN?CHA:DOWN;           //DOWN取小                  }*/                                                       }             if(n*c%b==0){                printf("%I64d\n",n*c/b);             }             else{                  up=c*n;                  down=b;                  while(1){                             //更相减损术(第二次约分)                        cha=up-down;                        if(down==1){                    //无公因子                            a=c/b;                           c=c*n%b;                           break;                        }                        if(cha==down&&cha!=1){          //有公因子cha                            c=c*n/cha;                           b=b/down;                           a=c/b;                           c=c%b;                           break;                                                   }                        up=cha>down?cha:down;                        down=cha<down?cha:down;                  }                   size1=size2=0; //size1,size2分别为整数部分的位数和分子的位数                   n1=a;                    n2=b;                   while(n1!=0){     //获得分母位数                          size1++;                          n1/=10;                    }                   while(n2!=0){     //获得分子位数                          size2++;                          n2/=10;                    }                   //按题目要求的格式打印结果                   for(i=0;i<=size1;i++) printf(" ");                       printf("%I64d\n",c);                       printf("%I64d ",a);                   for(i=0;i<size2;i++) printf("-");                       printf("\n");                   for(i=0;i<=size1;i++) printf(" ");                       printf("%I64d\n",b);             }                       }    }  }

我把第一次约分过程去掉了,在本地测试 n 只能达到20,但是没能AC,说明杭电的测试数据是一定含有20~40范围的大笑

所以就不用考虑字符串或二进制的什么去计算大数的麻烦了。






0 0
原创粉丝点击