杭电 acm 1099


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
340463 58 ------
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值