
蓝桥杯2021年第十二届省赛真题-杨辉三角形 - C语言网 (dotcpp.com)https://www.dotcpp.com/oj/problem2610.html
参考:
2021第十二届蓝桥杯省赛AB组C++组 杨辉三角形_skgion的博客-CSDN博客
二分法的边界问题详细分析_Lin_RD的博客-CSDN博客_二分法如何确定边界
这道题思路:
1.杨辉三角形——>组合数——>组合数的解法;
2.找规律——>可以把杨辉三角形对半分,斜着看,从左往右数第x条斜着的上的数是mCx,m是从2*x开始的数(如下方举例)——>每条边都单调递增,找数字通过二分找;
例如:
从2开始的那条斜边:2-3-4-5-6-……即为2C1,3C1,4C1,5C1,6C1……
从6开始的那条斜边:6-10-15-21-……即为4C2,5C2,6C2,7C2……
从20开始的那条斜边:20-35-56……即为6C3,7C3,8C3……
解题时:
1.按计算器发现:30C15=155117520>1E9,28C14=4011660,所以可以从 左数第14条边 向 第一条边找(srds 解题网站上从第8条边开始找也能过)
2.组合数的计算:用数学公式直接算
long long ans=1;//直接算组合数,q是下面的,x是上面的,ans是结果
for(int i=1,j=q-x+1;i<=x;i++,j++)ans=ans*j/i;
因为这样算组合数,ans是递增,所以当ans大于要找的数n时,直接返回ans(这个时候ans虽然不是组合数的答案,但也是比n大的)
(一开始用数组算组合数c[i][j]=c[i-1][j]+c[i-1][j-1];,结果时间还没炸,空间先炸了orz)
3.二分法:
设x是要找的那条边的序号。L=2*x,因为所有的边开始的第一个数字都是(2*x)Cx,R=n,因为最坏的结果是nC1。二分要查找的区间是[l,r]闭区间(具体的可以看参考网址中的二分法),同时一条边上的数(除了第0条边)都是严格单调递增(每个数都不一样),所以mid找到了就可以输出了。
4.如何确定n是第几个数:设n=qCx,然后找规律:
6=4C2,在第13个数-->(1+2+3+4)+2+1
10=5C2,在第18个数-->(1+2+3+4+5)+2+1
7=7C1,在第30个数-->(1+2+3+4+5+6+7)+1+1
……
所以,n=qCx,数的位置:(1+2+3+……+q)+x+1=(q+1)*q/2+x+1;
#includeusing namespace std; long long n; long long C(long long q,long long x) { long long ans=1; for(int i=1,j=q-x+1;i<=x;i++,j++){ ans=ans*j/i; if(ans>n)return ans; } return ans; } bool check(long long x) { long long l=2*x,r=n,q;//mid要在l和r闭区间里面! while(l<=r) { long long mid=l+(r-l)/2; q=C(mid,x); if(q>n){r=mid-1;} else if(q >n; for(int i=14;i>=0;i--){ if(check(i))break; } return 0; }
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)