杨辉三角 x

杨辉三角是美丽的数学结晶,其结论往往多蕴含自然之美.

                ——以下内容均摘抄自题解.

例题:

洛谷P1762  偶数

正如这题所示,数据在n<=10^15的范围内则引导我们去寻找空间更节省,速率更高效的算法。

首先,很明显,杨辉三角之特点在于其行数即等于每行的数字数。因此,可以很容易使用求和公式求出1到n行一共有多少个数字。

其次,通过观察,可以发现,奇数个数比偶数个数更有规律,其规律在于:

  1. 每行奇数个数一定为2^k(k为自然数)
  2. 当行数恰为2^k(k为自然数)时,奇数个数为2^k,偶数个数为零
  3. 当行数恰为2^k(k为自然数)时,奇数个数和恰为3^(k-1)
  4. 更巧妙的是:这个规律能更加扩展到一个不为2^k的数上,因为每一个数,都能分解为若干项2^k的和的形式。

举个例子吧:当n=2333;

2333= 2048+256+16+8+4+1

通过暴力程序,我们可以找出2333的所有奇数个数为190985

那么,我们找出如下数字

行数 所有奇数个数

2048 177147

256 6561

16 81

8 27 4 9 1 1

我们可以巧妙发现:177147 + 6561*2 + 81*4 + 27*8 + 9*16 + 1*32恰好等于190985!

那么,通过以上的探索,我们就能通过对n的分解,求出奇数总个数。

所以,偶数总个数也就不难得出了。

  1. 这样,我们就将一个看起来很困难的大量数求和,降级为极具规律性的数学公式求法。问题也顺理成章转化为如何将一个数分解为若干项2^k的和的形式。通过分析,我们知道算法的复杂度是O(logn)级的,足够通过所有的数据。
  2. 这道题目构思精巧,逻辑严密,能够告诉我们规律的寻找是一个漫长的探索过程,但是一旦得出了规律,世间万物自然水落石出!这个算法的正确性能够通过数学证明的,此处不赘述。
  3. 不要忘了膜题目要求的数字哦!

下面附探索规律的表格:

首先找规律什么的....(除了这个,其实也不一定对~~~~)

/*
                                         前  前        前    前
                                    每   i   i     每   i   i
                                    排   排   排   排   排  排
                                    偶   偶   偶   奇   奇   奇
                                    数   数   数   数   数  数
                                    个   个   和   个   个   和
*/
                  1                 0    0    0   1    1    1
                 1 1                0    0    0   2    3    3
                1 2 1               1    1    2   2    5    5
               1 3 3 1              0    1    2   4    9    7
              1 4 6 4 1             3    4    16  2    11    9
            1 5 10 10 5 1           2    6    26  4    15   21
          1 6 15 20 15 6 1          3    9    58  4    19    53
        1 7 21 35 35 21 7 1         0    9    58  8    27  128
      1 8 28 56 70 56 28 8 1        7    16   254  2    29  130
    1 9 36 84 126 126 84 36 9 1     6    22   746  4    33  150
         ......

大佬给出的:

// 行数 该行奇数 奇数和 偶数 偶数和   总数
    1     1     1     0    0        1
    2  (  2)    3     0    0        3
    3  (  2)    5     1    1        6
    4  (  4)    9     0    1        10
    5  (  2)   11     3    4        15
    6  (  4)   15     2    6        21
    7  (  4)   19     3    9        28
    8  (  8)   27     0    9        36
    9  (  2)   29     7    16       45
   10  (  4)   33     6    22       55
   16  ( 16)   81     0    55       136
   32  ( 32)  243     0    285      528
   64  ( 64)  729     0    1351     2080
  128  (128)  2187    0    6069     8256
  256  (256)  6561    0    26335    32896
  512  (512)  19683   0    111645   131328
 1024 (1024)  59049   0    465751   524800
 2048 (2048)  177147  0    1921029  2098176
 4096 (4096)  531441  0    7859215  8390656

下面附探索规律的辅助程序:

#include <cstdio>
using namespace std;

int t, i, j, ou, line, e, tot;
int mp[10005][10005];
int judge(int x)
{
    int v=1;
    while (v<x)
    {
        v *=2;
    }
    if (v==x) return 1;
    else return 0;
}
int main()
{//  Input an integer in 10000!
    scanf("%d",&e);
    mp[1][1]=1;
    ou = line = 0;
    tot = 1;
//行数(该行总数) 该行奇数 所有奇数 该行偶数 所有偶数 总数
    printf("    1     1      1     0     0     1\n");
    for (i=2; i<=e; ++i)
    {
        line=0;
        for (j=1; j<=i; ++j)
        {
            mp[i][j]=mp[i-1][j-1]+mp[i-1][j];
            if (mp[i][j]%2==0) ++line;
        }
        ou += line;
        tot += i;
        if (judge(i)==1)//保留该行可只查看N=2^k(k为自然数)的结果,若省略则查看所有结果
        printf("%5d %5d %5d %5d %5d %5d\n", i, i-line, tot-ou, line, ou, tot);
    }
    return 0;
}

附参考主程序:

#include <cstdio>
#define mo 1000003
using namespace std;

long long n, d, z, ans, a[55], b[55], v, p;
int i, t;
int main()
{
    scanf("%lld",&v);
    n = v;
    z = 1;
    d = z << 50; //因为2^50恰好大于10^15
    t = 50;
    while (n != 0)
    {
        if (n >= d)
        {
            n = n-d;
            a[++a[0]] = t; //将2^t 的t存入数组中
        }
        d /= 2;
        t--;
    }

    b[0] = 1;
    for (i=1; i<=a[1]; ++i)
        b[i]=(b[i-1]*3)%mo; //进行预处理,准备好3^t 的数字在数组b中

    for (i=1; i<=a[0]; ++i)
        ans += b[a[i]]*(long long)(z << i-1); //求所有奇数个数的和

    p = (((z+v%mo)*(v%mo))/2); //求和公式
    p %= mo;
    ans %= mo;
    if (p<ans) p += mo;
    p = (p-ans)%mo; //总个数减去所有奇数个数就是偶数个数了
    printf("%lld\n",p);
    return 0;
}
时间: 2024-08-30 02:23:21

杨辉三角 x的相关文章

LeetCode (13) Pascal&#39;s Triangle (杨辉三角 )

题目描述 Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return 从第三行开始,每行除了最左边和最右边两个数为1,其他数字都是上一行中相邻两个数字之和.根据上述规则可以写出下面的代码: class Solution { public: vector<vector<int> > generateRow1() { vector<in

杨辉三角

1 package com.llh.demo; 2 3 /** 4 * 杨辉三角 5 * 6 * @author llh 7 * 8 */ 9 public class Test { 10 /* 11 * 杨辉三角 12 */ 13 public static void main(String[] args) { 14 int[] a = new int[11]; 15 int num = 1; 16 // 17 for (int i = 1; i <= 10; i++) { 18 for (i

杨辉三角实例菱形实例

杨辉三角实例 public class Hui { public static void main (String [] args){ int [][] a =new int [10][10]; for(int i=0;i<a.length;i++){ for(int j=0;j<=i;j++){ if(j==0||i==j){ System.out.print(" "+(a[i][j]=1)); }else {a[i][j]=a[i-1][j-1]+a[i-1][j];

js算法集合(二) javascript实现斐波那契数列 (兔子数列) Javascript实现杨辉三角

js算法集合(二)  斐波那契数列.杨辉三角 ★ 上一次我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法,这次,我们来对斐波那契数列和杨辉三角进行研究,来加深对Javascript的理解. 一.Javascript实现斐波那契数列 ①要用Javascript实现斐波那契数列,我们首先要了解什么是斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为

使用Java打印杨辉三角

package 杨辉三角; import java.util.Scanner; public class 三角 { private static Scanner scn; public static void main(String[] args) { scn = new Scanner(System.in); System.out.println("请输入数据"); int n = scn.nextInt(); //定义一个二维数组 int [][] array = new int

Java的二维数组的应用及杨辉三角的编写

(1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个,即该位置上的元素在该行上最大,在该列上最小(注:一个二维数组也可能没有这样的鞍点). /** * * @author liuhui *@version Java上机实验三 *@time 2016.10.30 */ public class javatest2 { public static int

实现杨辉三角的10种解法--体验Python之美

本文收集了使用python实现杨辉三角的多种解法,主要为网上收集,也有一些是自己写的.从中可以体会python编写一个算法的不同思想和Python语法的特点. 杨辉三角是什么?还是度娘吧,看起来像是这样的:                          1                          1   1                           1   2   1                         1   3   3   1               

如何用C++打印杨辉三角

下面是杨辉三角的一部分,我们观察观察它有什么规律: 1 1      1 1     2     1 1     3     3     1 1     4     6     4     1 1     5    10    10    5    1 1     6    15    20   15    6    1 1     7     21    35   35   21   7    1 ................ 通过观察不难发现,三角的两边都是1,而且除边界外的每个数的值都

Pascal&#39;s Triangle II 杨辉三角

1 class Solution { 2 public: 3 vector<int> getRow(int rowIndex) { 4 vector<vector<int>> tri; 5 if(rowIndex==0) 6 { 7 vector<int> c; 8 c.push_back(1); 9 return c; 10 } 11 vector<int> b; 12 b.push_back(0); 13 b.push_back(1); 14

C输出帕斯卡三角(杨辉三角)递归实现

1 /*帕斯卡三角形(杨辉三角)*/ 2 int Recursive_Pascal_Triangle( int i, int j ) 3 { 4 if( (j == 0) || (i == j) ) 5 return 1; 6 else{ 7 return Recursive_Pascal_Triangle(i-1,j-1) + Recursive_Pascal_Triangle( i-1, j ); 8 } 9 } 10 11 /*输出三角形*/ 12 void display_triangl