第12届蓝桥杯省赛 杨辉三角形

在这里插入图片描述
在这里插入图片描述
问题:输入一个数N,求N第一次在杨辉三角中出现的位置。

因为杨辉三角是左右对称的,因此本篇我们只关注杨辉三角左半边的部分。杨辉三角第row行col列的元素值等于组合数C(row, col),例如第6行第3列元素等于C(6, 3) = 20。另外,如果一个数在杨辉三角左半边出现过两次,设出现的位置分别为(row1, col1)和(row2, col2)且col2 > col1,则一定有row1 > row2。根据这个性质我们从大到小遍历每个列,对于一个列我们从小到大遍历每个行并且求该列该行元素的值,如果元素的值超过了N则继续遍历下个更小的列。

#include <iostream>
using namespace std;

long long C(long long n, long long m) { //计算组合数C(n, m)
    long long ans = 1;
    for (long long i = 1; i <= m; ++i) ans = ans * (n - m + i) / i;
    return ans;
}

long long Pos(long long row, long long col) { //计算row行col列的元素是杨辉三角的第几个元素
    return (row + 1) * row / 2 + col + 1;
}

int main()
{
    long long N;
    cin >> N;
    long long max_col; //因为是从大到小遍历每列,所以列数需要有个最大值
    for (max_col = 0; C((max_col + 1) * 2, max_col + 1) <= N; ++max_col) ; //第col列的起始位置是(col * 2, col),如果(col * 2, col)处的元素大于N,就没必要遍历第col列了
    for (long long col = max_col; col >= 0; --col) { //由大到小遍历每一列
        if (col == 0) { //特判,如果遍历到第0列直接输出1
            cout << "1";
            break;
        }
        if (col == 1) { //特判,如果遍历到第1列直接输出Pos(N, 1)
            cout << Pos(N, 1);
            break;
        }
        long long row = col * 2, c = C(row, col); //row是当前行数,c是(row, col)位置的元素
        while (c < N) { //遍历每一行直到c不小于N
            row++;
            c = c * row / (row - col);
        }
        if (c == N) { //如果c等于N便找到了N第一次出现的位置
            cout << Pos(row, col);
            break;
        }
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值