ZCMU1326: 杨辉三角

文章探讨了在计算杨辉三角中遇到的二项式系数(C(n,m))可能导致的整数溢出问题,通过使用长整型(longlong)来避免溢出,并调整计算逻辑,确保正确计算大数值的组合数。通过示例代码展示了解决方案,并给出了不同尝试的结果对比。
摘要由CSDN通过智能技术生成

时间限制: 1 Sec 内存限制: 128 MB

提交: 1733 解决: 699

[提交][状态][讨论版]

题目描述

还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

输入

输入数据包含多个测试实例,每个测试实例的输入只包含一个正整数n(1<=n<=30),表示将要输出的杨辉三角的层数。

输出

对应于每一个输入,请输出相应层数的杨辉三角,每一层的整数后面用一个空格,每一个杨辉三角后面加一个空行。

样例输入

2
3

样例输出

1
1 1 


1 1
1 2 1

提示

来源

[提交][状态][讨论版]

【想法】

记第m行,第t个(二项式的上角标)。而输入为1~n行,利用双循环实现(先i,后j)实现一行一行的输出,i为输出时的第几行,那么m=i-1,而t的范围是1~i-2。

那么要点就是实现C(n,m)了(二项式,键盘打不出来)。

【答案】

#include<stdio.h>

int main()
{
    int n,m,i,j,z,t;
    long long sum,sum_1;
    
    while( ~scanf("%d",&n) ){
        
        for(i=1;i <=n;i++){
            printf("1 ");
            
            for(j=1;j <= i-2;j++){
                sum=1,sum_1=1;
                t=j;
                if(t > (i-1)/2 ) t=(i-1)-t;
                
                for( z=i-t;z<=i-1;z++) sum*=z; 
                for( z=2;z <= t;z++) sum_1*=z;
                
                printf("%lld ",sum/sum_1);
            }
            (i > 1)?printf("1 \n"):printf("\n");
        }
        printf("\n");
        
    } 
      return 0;
}

【错误集合T_T】

#include<stdio.h>


int main()
{
    int n,m,i,j,z,c,sum,sum_1;
    
    while( ~scanf("%d",&n) ){
        for(i=1;i <=n;i++){
            printf("1 ");
            for(j=1;j <= i-2;j++){
                sum=1,sum_1=1;
                for( z=i-j;z<=i-1;z++) sum*=z; 
                for( z=2;z <= j;z++) sum_1*=z;
                printf("%d ",sum/sum_1);
            }
            (i > 1)?printf("1 \n"):printf("\n");
        }
        printf("\n");
        
    } 
      return 0;
}

前面是没太大毛病,我也就交了……直接WA

#include<stdio.h>
//错误之后检验
int main()
{
    int n,m,i,j,z,c,sum,sum_1;
    
    while( ~scanf("%d",&n) ){
        for(i=1;i <=n;i++){
            printf("1_");
            for(j=1;j <= i-2;j++){
                sum=1,sum_1=1;
                for( z=i-j;z<=i-1;z++) sum*=z; 
                for( z=2;z <= j;z++) sum_1*=z;
                printf("%d_",sum/sum_1);
            }
            (i > 1)?printf("1_\n"):printf("\n");
        }
        printf("\n");
        
    } 
      return 0;
}
14
1_
1_1_
1_2_1_
1_3_3_1_
1_4_6_4_1_
1_5_10_10_5_1_
1_6_15_20_15_6_1_
1_7_21_35_35_21_7_1_
1_8_28_56_70_56_28_8_1_
1_9_36_84_126_126_84_36_9_1_
1_10_45_120_210_252_210_120_45_10_1_
1_11_55_165_330_462_462_330_165_55_11_1_
1_12_66_220_495_792_924_792_495_220_66_12_1_
1_13_78_286_715_1287_1716_1716_1287_715_286_-29_4_1_//开始错误,找到错误原因
//首先怀疑C(n,m)的算法问题
#include<stdio.h>
#include<string.h>

int main()
{
    int n,m,i,j,z,c,sum,sum_1;
    
    while( ~scanf("%d %d",&m,&n) ){
    
        sum=1,sum_1=1;
        for( z=m-n+1;z<=m;z++) sum*=z; 
        printf("分子=%d\n",sum);
        for( z=2;z <= n;z++) sum_1*=z;
        printf("分母=%d\n",sum_1);
        printf("C(n,m)=%d_\n\n",sum/sum_1);
        
        
    }
      return 0;
}
13 3
分子=1716
分母=6
C(n,m)=286_
13 4
分子=17160
分母=24
C(n,m)=715_
13 5
分子=154440
分母=120
C(n,m)=1287_
13 6
分子=1235520
分母=720
C(n,m)=1716_
13 9
分子=259459200
分母=362880
C(n,m)=715_
13 10
分子=1037836800
分母=3628800
C(n,m)=286_
13 11
分子=-1181456896//问题所在,int溢出了
分母=39916800
C(n,m)=-29_

改为double或long long都可以(都试过了)

//改为long long,但是eg:
29 28
分子=-2037930108//依旧错误
分母=-767727258
C(n,m)=29_
//=======
13 11
分子=-1181456896
分母=39916800
C(n,m)=78_
13 12
分子=1932053504
分母=479001600
C(n,m)=13_
29 28
分子=-1241513984
分母=-1375731712
C(n,m)=1_    //错误
29 1
分子=29
分母=1
C(n,m)=29_
29 10
分子=1168737792
分母=3628800
C(n,m)=20030010_
29 19
分子=755630080
分母=109641728
C(n,m)=-33_
29 11
分子=731181568
分母=39916800
C(n,m)=34597290_
29 12
分子=276366336
分母=479001600
C(n,m)=51895935_
29 13
分子=403260416
分母=1932053504
C(n,m)=67863915_
29 14
分子=-2137767936
分母=1278945280
C(n,m)=77558760_
29 15
分子=-2001747968
分母=2004310016
C(n,m)=7026123_
29 16
分子=2040299520
分母=2004189184
C(n,m)=-23747_

【改为long long &&对半分格式】

#include<stdio.h>
#include<string.h>

int main()
{
    int n,m,i,j,z,c;
    long long sum,sum_1;
    
    while( ~scanf("%d %d",&m,&n) ){
    
        sum=1,sum_1=1;
        if(n>m/2) n=m-n;
        for( z=m-n+1;z<=m;z++) sum*=z; 
        printf("分子=%lld\n",sum);
        for( z=2;z <= n;z++) sum_1*=z;
        printf("分母=%lld\n",sum_1);
        printf("C(n,m)=%lld_\n\n",sum/sum_1);
        
        
    }
      return 0;
}
29 10
分子=72684900288000
分母=3628800
C(n,m)=20030010_
29 11
分子=1381013105472000
分母=39916800
C(n,m)=34597290_
29 12
分子=24858235898496000
分母=479001600
C(n,m)=51895935_
29 13
分子=422590010274432000
分母=6227020800
C(n,m)=67863915_
29 14
分子=6761440164390912000
分母=87178291200
C(n,m)=77558760_
29 15
分子=6761440164390912000
分母=87178291200
C(n,m)=77558760_
29 16
分子=422590010274432000
分母=6227020800
C(n,m)=67863915_

【如果不对分】

#include<stdio.h>
#include<string.h>

int main()
{
    int n,m,i,j,z,c;
    long long sum,sum_1;
    
    while( ~scanf("%d %d",&m,&n) ){
    
        sum=1,sum_1=1;
        //if(n>m/2) n=m-n;//就这一条
        for( z=m-n+1;z<=m;z++) sum*=z; 
        printf("分子=%lld\n",sum);
        for( z=2;z <= n;z++) sum_1*=z;
        printf("分母=%lld\n",sum_1);
        printf("C(n,m)=%lld_\n\n",sum/sum_1);
        
        
    }
      return 0;
}
29 10
分子=72684900288000
分母=3628800
C(n,m)=20030010_
29 11
分子=1381013105472000
分母=39916800
C(n,m)=34597290_
29 12
分子=24858235898496000
分母=479001600
C(n,m)=51895935_
29 13
分子=422590010274432000
分母=6227020800
C(n,m)=67863915_
29 14
分子=6761440164390912000
分母=87178291200
C(n,m)=77558760_
29 15
分子=9187882097315921920
分母=1307674368000
C(n,m)=7026123_
29 16
分子=-496859153543954432
分母=20922789888000
C(n,m)=-23747_
29 17
分子=-6459168996071407616
分母=355687428096000
C(n,m)=-18159_
29 28
分子=-7055958792655077376
分母=-5968160532966932480
C(n,m)=1_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值