蓝桥杯2021年第十二届省赛-杨辉三角形

蓝桥杯2021年第十二届省赛真题-杨辉三角形 - C语言网 (dotcpp.com)https://www.dotcpp.com/oj/problem2610.html

参考:

2021第十二届蓝桥杯省赛AB组C++组 杨辉三角形_skgion的博客-CSDN博客

二分法的边界问题详细分析_Lin_RD的博客-CSDN博客_二分法如何确定边界

这道题思路:

1.杨辉三角形——>组合数——>组合数的解法;

2.找规律——>可以把杨辉三角形对半分,斜着看,从左往右数第x条斜着的上的数是mCx,m是从2*x开始的数(如下方举例)——>每条边都单调递增,找数字通过二分找;

例如:

从2开始的那条斜边:2-3-4-5-6-……即为2C1,3C1,4C1,5C1,6C1……

从6开始的那条斜边:6-10-15-21-……即为4C2,5C2,6C2,7C2……

从20开始的那条斜边:20-35-56……即为6C3,7C3,8C3……

蓝桥杯2021年第十二届省赛-杨辉三角形_第1张图片

 解题时:

 1.按计算器发现:30C15=155117520>1E9,28C14=4011660,所以可以从 左数第14条边 向 第一条边找(srds 解题网站上从第8条边开始找也能过)

2.组合数的计算:用数学公式直接算

\binom{n}{m}=\frac{n!}{(n-m)!*m!}=\frac{(n-m+1)*(n-m+2)*...*n}{1*2*3*...*m}

    long long ans=1;//直接算组合数,q是下面的,x是上面的,ans是结果
    for(int i=1,j=q-x+1;i<=x;i++,j++)ans=ans*j/i;

因为这样算组合数,ans是递增,所以当ans大于要找的数n时,直接返回ans(这个时候ans虽然不是组合数的答案,但也是比n大的)

(一开始用数组算组合数c[i][j]=c[i-1][j]+c[i-1][j-1];,结果时间还没炸,空间先炸了orz)

3.二分法:

设x是要找的那条边的序号。L=2*x,因为所有的边开始的第一个数字都是(2*x)Cx,R=n,因为最坏的结果是nC1。二分要查找的区间是[l,r]闭区间(具体的可以看参考网址中的二分法),同时一条边上的数(除了第0条边)都是严格单调递增(每个数都不一样),所以mid找到了就可以输出了。

4.如何确定n是第几个数:设n=qCx,然后找规律:

6=4C2,在第13个数-->(1+2+3+4)+2+1

10=5C2,在第18个数-->(1+2+3+4+5)+2+1

7=7C1,在第30个数-->(1+2+3+4+5+6+7)+1+1

……

所以,n=qCx,数的位置:(1+2+3+……+q)+x+1=(q+1)*q/2+x+1;

#include
using namespace std;
long long n;
long long C(long long q,long long x)
{
    long long ans=1;
    for(int i=1,j=q-x+1;i<=x;i++,j++){
        ans=ans*j/i;
        if(ans>n)return ans;
    }
    return ans;
}
bool check(long long x)
{
    long long l=2*x,r=n,q;//mid要在l和r闭区间里面!
       while(l<=r)
        {
            long long mid=l+(r-l)/2;
            q=C(mid,x);
            if(q>n){r=mid-1;}
            else if(q>n;
    for(int i=14;i>=0;i--){
        if(check(i))break;
    }
    return 0;
}

你可能感兴趣的:(蓝桥杯)