第十二届蓝桥杯省赛第一场C++B组真题(杨辉三角形)

下面的图形是著名的杨辉三角形:

如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:

1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 4, 6, 4, 1, ...

给定一个正整数 N,请你输出数列中第一次出现 N 是在第几个数?

输入格式

输入一个整数 N。

输出格式

输出一个整数代表答案。

数据范围

对于 20%的评测用例,1≤N≤10;
对于所有评测用例,1≤N≤10^9。

输入样例:

6

输出样例:

13

杨辉三角的一些性质:左右对称,所以只要在杨辉三角右半边出现过的数都会在左半边出现过,且位置是对称的,所以答案一定是在左半边,还有就是对于每一斜行和竖行从上至下是依次增大的,需要明确的一点是所有的数都会在杨辉三角中出现,比如x,一定会有C(x,1)对应于x,所以不用担心有无解的情况,但是我们需要找到数值为x的最靠上的位置就需要从下往上枚举,因为如果x第一次出现在(i,j)这个位置,那么这个位置左上和上方以及右上的数都会比x要小,所以我们可以枚举斜行,利用二分来枚举在每一斜行中出现的位置即可,注意是从下往上枚举:

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
ll C(ll a,ll b)//求组合数 
{
    ll ans=1;
    for(int i=a,j=1;j<=b;i--,j++)
        ans*=i,ans/=j;
    return ans;
}
ll n;
bool check(int k)//枚举第k斜行 
{
    ll l=2*k,r=max(l,n);
    while(l<r)
    {
        ll mid=l+r>>1;
        if(C(mid,k)>=n) r=mid;
        else l=mid+1;
    }
    if(C(l,k)==n)
    {
        printf("%lld",l*(l+1)/2+k+1);//注意组合数是从C(0,0)开始的 
        return true;
    }
    return false;
}
int main()
{
    cin>>n;
    for(int i=16;;i--)//枚举斜行 
        if(check(i)) break;
    return 0;
}

### 蓝桥杯 C++ 编程题解及学习资源 #### 题目解析与算法设计 蓝桥杯作为一项面向全国范围的技术竞,其题目涵盖了基础到高的各种难度层次。以下是针对不同类型的蓝桥杯 C++ 编程题目的分析: 1. **查找整数问题** 对于在列表 `lst` 中找到第 n 小的整数这一类问题,可以采用排序法或者堆排序的方式实现。通过先对数进行升序排列,再选取索引为 `(n-1)` 的元素即可得到目标值[^1]。 2. **杨辉三角计算** 杨辉三角是一个经典的合数学问题,在蓝桥杯的基础训练中也有所涉及。可以通过二维数存储每一层的结果,并利用递推关系完成构建。具体而言,当前项等于上一层相邻两项之和。 3. **表达式修改运算逻辑** 当遇到需要调整算术表达式的场景时,例如将加号替换减号并重新评估结果的任务,则需注意操作符优先的变化以及括号的作用。按照引用中的描述,最终公式应写成如下形式: ```cpp res = tmp - (j + (j - 1)) + j * (j - 1); ``` 这里特别强调乘法相较于加减具有更高的执行顺序[^2]。 4. **浮点数转R格式处理** 关于小蓝研究的新颖数据表现方式——即把正实数值映射至特定规则下的整型编码过程,主要依赖输入参数 `d` 和转换因子 `n` 完成定义。整个流程大致分为三步走:取整部分、分数部分分离;依据指定精度舍入近似;最后拼接形成完整的十进制字符串表示[^3]。 #### 推荐的学习材料与工具链接 为了更好地准备蓝桥杯,建议参考以下几类优质资源: - 官方文档与历年真题集锦; - 各大在线评测平台上的专项练习专区; - 技术社区分享的经验帖和技术博文集合。 ```cpp // 示例代码片段展示如何生成前五行杨辉三角形 #include <iostream> using namespace std; int main() { int rows = 5; long long C[rows][rows]; for(int i=0;i<rows;i++) { for(int j=0;j<=i;j++) { if(j==0 || j==i) C[i][j]=1; else C[i][j]=(C[i-1][j-1]+C[i-1][j]); cout<<C[i][j]<<" "; } cout<<"\n"; } return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值