当前位置:   article > 正文

【蓝桥杯C++ B组】杨辉三角形_蓝桥杯b 杨辉三角

蓝桥杯b 杨辉三角

二分

1、思路怎么想?

(1)因为杨辉三角是左右对称的,所以n最早出现的位置只能是左半部分。

所以,只看左半部分,

(2)每一行中越靠近中间的数越大,每一斜行中越往下越大。 所以从最下面的斜行往上枚举。

 (3) n最大1e9,C(34, 17) > 1e9, C(32, 16) < 1e9,因此只要枚举前16个斜行即可!

(4) 可以发现性质:

1)每一斜行从上到下递增

2)每一横行从中间到两边依次递

因此我们直接从中间对称轴倒序二分找起即可,

(5)二分查找每一斜行,

1)因为,每个斜行的第一个数是C(2k, k)依次为C(2k + 1, k)...,并且还是递增的。

只有上标变,所以我们只枚举上标,从2k到max(n , l)。

2)为什么是到max(n , l)?

是因为,从中间沿斜行往下递增,所以,如果n这个数在该斜行内,那么必然n > l

3)因此,

二分的左右端点:l:2k,r:max(n, l)

右端点一定不能比左端点小!

特例:否则当n=1时,会出问题!

(6)因为二分查找的是上标,所以我们还需写一个函数,去求组合数

用于与数字n比较,查找

(7)最后查找到之后,求该数的位置

C(r, k)对应的顺序值为:(r + 1) * r / 2 + k + 1

2、代码怎么写?

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std;
  5. typedef long long LL;
  6. int n;
  7. //3、求组合数
  8. // C(a, b) = a!/b!(a-b)! = a * (a-1) .. b个 / b!
  9. LL c(int a , int b)
  10. {
  11. LL res = 1;
  12. for( int i = a , j = 1 ; j <= b ; i -- , j ++ )
  13. {
  14. res = res * i / j;
  15. if(res > n) return res;// 大于n没有意义并且防止爆LL
  16. }
  17. return res;
  18. }
  19. bool check( int k )
  20. {
  21. //2、二分查找
  22. // 二分该斜行,找到大于等于该值的第一个数
  23. // 左边界2k,右边界为max(l, n)取二者最大即可!
  24. LL l = 2 * k , r = max(l , (LL)n);
  25. while(l < r)
  26. {
  27. LL mid = l + r >> 1;
  28. if(c(mid , k) >= n) r = mid;//c(mid , k)表示组合数
  29. else l = mid + 1;
  30. }
  31. if(c(r , k) != n) return false;//不在该斜行中
  32. cout << (r + 1) * r / 2 + k + 1 << endl;
  33. //C(r, k)对应的顺序值为:(r + 1) * r / 2 + k + 1
  34. return true;
  35. }
  36. int main()
  37. {
  38. cin >> n;
  39. //1、枚举每一斜行,从第16个斜行开始枚举
  40. for( int k = 16 ; ; k -- )
  41. if(check(k))
  42. break;
  43. return 0;
  44. }

一股温暖的激流刹那间漫过了他的心间。那灯光下,有他亲爱的家——亲人们的脸庞都在他的眼前浮现出来了。

                                             ——《平凡的世界》第二十三章

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/439353
推荐阅读
相关标签
  

闽ICP备14008679号