杨辉三角形 -蓝桥 -java

杨辉三角形


最大运行时间:1s
最大运行内存: 256M


题目描述:

下面的图形是著名的杨辉三角形:
请添加图片描述
如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,⋯

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

输入描述
输入一个整数 N。

输出描述
输出一个整数代表答案。

输入输出样例
示例 1
输入
6
输出
13

评测用例规模与约定
对于 20%​​ 的评测用例,1≤N≤10​; 对于所有评测用例,1≤N≤1000000000。


给定一个数 求出他在杨辉三角中第一次出现的位置


emmmmmmm

来一个稍微大点的杨辉三角
在这里插入图片描述
可以很明显的看出杨辉三角是以中间对称的

那么第一次的位置 肯定在左半边


红色框框 框出的为对称线
在这里插入图片描述

箭头表示 当前从对称线开始 往下基本是该元素第一次出现的位置

注:
比如6 为 C(4, 2), 但是 C(6, 1) 也是
所以 是基本 第一次出现的位置 但不一定是绝对第一次出现
但左半边一定为数的第一次出现位置
在这里插入图片描述
我们可以发现每个箭头的直线线都是 C ( k ∗ 2 + 1 , k ) 、 C ( k ∗ 2 + 2 , k ) 、 . . . 、 C ( k ∗ 2 + n , k ) C(k * 2 + 1, k)、 C(k * 2 + 2, k)、... 、 C(k * 2 + n, k) C(k2+1,k)C(k2+2,k)...C(k2+n,k) 这样子的

起点 为 C ( k ∗ 2 , k ) C(k * 2, k) C(k2,k)
终点 为 C ( k ∗ 2 + ∞ , k ) C(k * 2 + \infty, k) C(k2+,k)


不过需要注意的是 他不能从左边的箭头的线到右边的箭头的线 开始找

也就是上面说的 6 = C(4, 2) = C(6, 1)

如果从左边开始找的话 那么找的位置就是 (6, 1)
可是实际上 (4, 2) 才是答案

所以需要从右边开始


所以我们就可以 从右到左的箭头一个个找下去

想想看 我们
起点 为 C ( k ∗ 2 , k ) C(k * 2, k) C(k2,k)
终点 为 C ( k ∗ 2 + ∞ , k ) C(k * 2 + \infty, k) C(k2+,k)
是这样的

如果这样找一个一个找下去的话 一定会超时的

所以就需要用到二分

但是二分的话 需要起始位置和终止位置

起始位置我能能确定是 k * 2

但是终止位置呢
我就看第二个箭头的那个直线
他是 1 ~ n 这样子的

所以我们最大是 n
终止位置设为 n 就好了


然后就是直接找了

我们先去看需要多少个箭头直线
我没看 如果箭头直线的起始位置都超过了 n 的话那么接下来的所有数都会是 超过 n 的

所以我们只需要找到第一个大于等于 n 的 C ( 2 ∗ i , i ) C(2 * i, i) C(2i,i) 的位置即可

然后就是从 右往左去看 箭头直线即可

二分找数的位置

然后 我们找到了数的位置之后呢

比如 (a, b) 这个位置

因为他是杨辉三角 所以 a 行 上面的是一个 1 ~ a - 1 的累加和 也就是 ∑ 1 a − 1 \sum_{1}^{a-1} 1a1

然后 多加一个1 就好了
因为 杨辉三角是从C(x, 0) 开始的

所以最后的位置是 ∑ 1 a − 1 + b + 1 \sum_{1}^{a-1} + b + 1 1a1+b+1


import java.io.*;
import java.math.*;
import java.util.*;

public class Main
{
	static long x;

	static long C(long n, long m)
	{
		long mul = 1;
		for (long i = 1; i <= m; i++)
		{
			mul = mul * (n - i + 1) / i;
			if (mul > x)
				break;
		}
		return mul;
	}

	static boolean is(int k)
	{
		long l = 2 * k, r = x;
		while (l < r)
		{
			long mid = l + r >> 1;
			if (C(mid, k) >= x)
				r = mid;
			else
				l = mid + 1;
		}
		if (C(l, k) != x)
			return false;

		out.println((l + 1) * l / 2 + k + 1);

		return true;
	}

	public static void main(String[] args)
	{
		x = sc.nextLong();
		if (x == 1)
			out.println(1);
		else
		{
			int k = 1;
			while (C(k * 2, k) < x)
				k++;

			for (int i = k; i >= 1; i--)
			{
				if (is(i))
					break;
			}
		}

		out.flush();
		out.close();
	}

	static Scanner sc = new Scanner(System.in);
	static PrintWriter out = new PrintWriter(System.out);
}

杨辉三角

二分查找
二分查找

等差数列求和公式


如果有说错的 或者 不懂的 尽管提 嘻嘻

一起进步!!!


闪现

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谢谢 啊sir

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值