蓝桥杯每日N题(杨辉三角形)

大家好 我是寸铁 希望这篇题解对你有用,麻烦动动手指点个赞或关注,感谢您的关注

不清楚蓝桥杯考什么的点点下方👇

考点秘籍

想背纯享模版的伙伴们点点下方👇

蓝桥杯省一你一定不能错过的模板大全(第一期)

蓝桥杯省一你一定不能错过的模板大全(第二期)

蓝桥杯省一你一定不能错过的模板大全(第三期)

蓝桥杯省一你一定不能错过的模板大全(第四期)!!!

想背注释模版的伙伴们点点下方👇

蓝桥杯必背第一期

蓝桥杯必背第二期

往期精彩回顾

蓝桥杯上岸每日N题 第一期(一)!!!

蓝桥杯上岸每日N题第一期(二)!!!

蓝桥杯上岸每日N题第一期(三)!!!

蓝桥杯上岸每日N题第二期(一)!!!

蓝桥杯上岸每日N题第三期(一)!!!

蓝桥杯上岸每日N题 第四期(最少刷题数)!!!

蓝桥杯上岸每日N题 第五期(山)!!!

蓝桥杯上岸每日N题 第六期(求阶乘)!!!

蓝桥杯上岸每日N题 第七期(小猫爬山)!!!

蓝桥杯上岸每日N题 第八期 (全球变暖)!!!

蓝桥杯每日N题 (消灭老鼠)

操作系统期末题库 第九期(完结)

LeetCode Hot100 刷题(第三期)

idea创建SpringBoot项目报错解决方案

数据库SQL语句(期末冲刺)

想看JavaB组填空题的伙伴们点点下方 👇

填空题

竞赛干货

算法竞赛字符串常用操作大全

蓝桥杯上岸必刷!!!(模拟/枚举专题)

蓝桥杯上岸必背!!! (第三期 DP)

蓝桥杯上岸必背!!!(第四期DFS)

蓝桥杯上岸必背!!!(第五期BFS)

蓝桥杯上岸必背!!!(第六期树与图的遍历)

蓝桥杯上岸必背!!!(第七期 最短路算法)

蓝桥杯上岸必背!!!(第八期 简单数论)

蓝桥杯上岸必刷!!!(进制、数位专题)

蓝桥杯上岸考点清单 (冲刺版)!!!

蓝桥杯上岸必背模板 (纯享版)

考点:二分+求组合数

分析

要在这堆数字中找到n
观察发现:
(1)三角形左右两边的数字对称
我们只需要看左半边的数字即可

(2)画一条中轴线在中间
发现中轴线上的点的值为C(2n,n)
找的时候,从内往外找,依次去枚举每一斜行。
为什么?
假设我们找到n,那外面的数字必然是小于n的,所以我们从内开始去找n。
第一次找到的数必定在左边且减少我们的枚举次数。

接下来怎么做?
我们从第16斜行去枚举中轴线上的起点开始,依次去枚举每一斜行
从中查找组合数,看能否二分出答案来

概念理清:

组合数:C(a,b)
a:底数–>当前枚举的斜行数–>二分的答案(r)
**b:**真数–>k

二分过程

不清楚二分的过程可以看下面的图:

在这里插入图片描述

图形解读:

组合数:C(a,b)
a:底数–>当前枚举的斜行数–>二分的答案(r)
b:真数–>k

枚举的是每一斜行,从中轴线的起点开始。
相当于我check一个k(枚举的斜行数),我二分的是当前这一斜行的组合数的底数。
根据二分原理,去更新mid的值。
再看我当前枚举的这一斜行C(mid,k)能否找到n
枚举这一斜行都找不到后,我再往前去枚举上一斜行,直至第一个斜行

求组合数

public static long C(long a,long b) {
	long res=1;
	for(long i=a,j=1;j<=b;i--,j++) {
		res=res*i/j;
		if(res>n)return res;
	}
	return res;
    }

杨辉三角形数字定位技巧

在数字序列的第几个位置(r+1)*r/2+k+1
r:组合数的底数

代码详解

import java.util.*;
public class Main{
  static int n;
  public static long C(long a,long b) {
     //求组合数
	long res=1;
	for(long i=a,j=1;j<=b;i--,j++) {
		res=res*i/j;
		if(res>n)return res;
	}
	return res;
    }
    
    public static boolean check(int k) {
	long l=2*k,r=Math.max(l,n);
    //记得l,n取max,否则最一开始当l>r时无法二分
	//C(l,r):l表示的是组合数底数的下界
	//       r表示的是组合数底数的上界
	
	//二分
	while(l<r) {
    long mid=l+r>>1;
	if(C(mid,k)>=n)r=mid;
	//更新我当前枚举的这一斜行组合数的底数
	//让它往上或往下走
	else l=mid+1;
	}
	
	if(C(r,k)!=n)return false;
	//找不到等于n的数,就返回false,去枚举下一斜行。
	
//C(r,k):二分出的组合数
//k:k表示的是列数,由于是从第0行开始,所以是k+1
//这样可以得出数字n在第几列。

//r:r表示的是行数,(1+r)*r/2可以得到数字在哪一行
//(1+r)*r/2再加上移动的第几列即k+1
//这样可以得到n在整个序列中是在第几个位置。
	System.out.println((1+r)*r/2+k+1);
	return  true;
    }
    
    public static void main(String []args){
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        for(int i=16;;i--){
            //C16的32小于1e9
            //从16斜行开始枚举
            //找到满足条件的数就break
            if(check(i))break;
        }
    }
}

创作不易,欢迎大家多多关注,Thankyou~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寸 铁

感谢您的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值