0
点赞
收藏
分享

微信扫一扫

杨辉三角规律

想溜了的蜗牛 2022-04-07 阅读 84
c++

在这里插入图片描述
在这里插入图片描述
图片来自acwing

#include <bits/stdc++.h>
/*#include <iostream>
#include <algorithm>
#include <set>*/
#define int long long 
using namespace std;
const int N=20;
int a[N][N];
void print(){
	for(int i=0;i<=N;i++)a[i][0]=1;//第0列全1 
	for(int i=1;i<=N;i++){
		for(int j=1;j<=i;j++){
			a[i][j]=a[i-1][j-1]+a[i-1][j]; 
		}
	}	
	for(int i=0;i<=N;i++){
		for(int j=0;j<=i;j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
} 
const int inf=0x3f3f3f3f;
int n; 
int res=inf;
int C(int a,int b){//C(5,2)=5*4/2/1
	int res=1;
	for(int i=a,j=1;j<=b;j++,i--){
		res=res*i/j;//边乘边除
		if(res>n)return res;//防止爆long long,反正大于n也不可能取这个值 
	}
	return res; 
}
bool fun(int k){//第k列
	int l=k*2;//每列第一个元素所在的行是列数*2噢
	int r=n;//根据第一列,n最晚出现在第n行
	while(l<r){
		int mid=(l+r)>>1;
		if(C(mid,k)<n){//第k列,mid这一行 小于n,这列有n就在下面 
			l=mid+1; 
		}
		//要是判断条件写成<=,则l=mid,要写成mid=(l+r+1)<<1 
		else r=mid;
	} 
/*	if(C(l+k,k)==n)return l*(l+1)/2+k+1;//加1是因为从0开始的
	else return inf;*/ 
	if(C(l,k)==n){
		cout<<r*(r+1)/2+k+1;
		return true;
	}
	return false;
//行数、列数指的都是在杨辉三角中的行列 !!!
//所以不是C(mid+k,k)	而是C(mid,k)
}
signed main() {
/*观察杨辉三角规律
1、原杨辉三角左右对称,某数第一次出现一定在左半边,前若干列
2、左右对称则从中间劈开,只看左半边,可发现中线上的元素的值
1 2 6 20,C(0*2,0),C(2,1),C(4,2),C(6,3)…
C(2*k,k),k=0,1,2,3…,当摆放成下三角形形式,k代表的就是列数
其实拟合第4条,也可以得知每列第一个元素位于的行数等于列数*2!
注意了 行数、列数指的都是在杨辉三角中的行列 !!! 
中线上的元素就是每列的从上往下第一个元素,也是该列最小的元素(每列从上往下递增)
以上这些感觉打印出下三角也不太好看,不太好劈成两半看,还是自己多补几行原杨辉三角
3、每列从上往下递增嘛,第1列的是差值为1的等差数列,所以n在杨辉三角中一定会存在,
最晚出现在第n行,这也将成为  二分 在每列中找到n出现的行 的依据(递增,行的上限) 
4、摆放成下三角形形式,m行n列的元素大小是C(m+n,n),行大于列,从0开始计数! 
在原杨辉三角里, m行n列的元素大小是C(m,n)!!! 
5、有这样的规律,C(34,17)就会超过1e18,所以只需要考虑前17列就ok 
总而言之,这题重在找到杨辉三角的规律 
*/
 	//print();
 	cin>>n;
 	for(int i=17;i>=0;i--){
 		if(fun(i))break;
 		//int ans=fun(i);
 		//if(ans<inf)res=min(res,ans);//其实肯定在靠左的列中 
 	}
 	/*从右往左枚举列,因为左半边三角形 每行从左往右递增,
	 第一次出现的位置自然需要行数尽可能小,如果第i列有n,
	 那么小于i的那些列里,n一定出现在下面,因为同行小于i列该行的值*/ 
 	//cout<<res;
	return 0;
}
举报

相关推荐

杨辉三角.java

杨辉三角(Java)

杨辉三角算法

leetcode:杨辉三角

杨辉三角(java)

杨辉三角展示

杨辉三角问题

0 条评论