杨辉三角形//第八届北京师范大学程序设计竞赛决赛

题目链接


杨辉三角形

Time Limit: 1500ms
Memory Limit: 65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                   
  •   

    LZM 同学比较牛, Lsy 最近也越来越生猛,他们思路快,代码速度神勇。近期惊闻此二人均要参加校赛,队里决定出些题目卡他们,因为他们的罢工给题目组留下了繁重的负担……(报复报复)
    于是, XsugarX 瞄准了 LZM 不太喜欢看的数学题目以及 Lsy 猜公式的喜好,奸笑中( ^.^ )。这个数学问题是个比较古老的问题,有如下图的三角形被称为杨辉三角形:
    1
    1 1
    1 2 1
    1 3 3 1
    1 4 6 4 1
    1 5 10 10 5 1
    我们记第一个 1 为第 0 行,往下依次编号。
    其中三角形左右两斜边上的数字均为 1 ,其他位置均为其两肩上的数之和。
    此两牛看到偶数就会觉得复杂,被卡的时间与偶数的个数成正比, XsugarX 希望能卡他们的时间越久越好。
    给定任意杨辉三角的行数 n ,请输出杨辉三角中 n 中总共有多少偶数。

    Input

      

    一个数 n 0<=n<=3,000,000 )。表示求杨辉三角前 n 行中偶数的个数。

    Output

      

    一个数 R 。表示在杨辉三角前 n 行中共有 R 个偶数,由于结果可能会很大,请输出 R mod 10,000,000 的结果。

    Sample Input

    4

    Sample Output

    4

    Source

    Author

    XsugarX

    Tags 


                                                                                                                                                                                                                                                   
    题解:杨辉三角形 分形题目,求杨辉三角形前 n 行的偶数个数。原型是基于一个定理:杨辉三角形的第 n 行中奇数个数等于 2k 个,k 为 n 表示为二进制时 1 的个数。因此,对于 n<=3000000 的数 据范围,可以线性的进行一次扫描,累和打表。 由于统计二进制位,复杂度 O(N)中的 N 会包含一小常数 C,C 为数字的长度。 大多数都是用分形来解决的,当然这也是个很自然的想法,效率会稍微低一 点。另 VIJOS 上有题目的加强版,题目数据 n<=10^50,需要根据上面的定理推倒公式, 然后快速幂+高精解决。 


    附代码

    方法1:

    #include<stdio.h>
    #include<math.h>
    #define N 10000000
    int a[3000001]={0};
    int gs(int n)
    {
        int k=0;
        while(n)
            {
                n=n&(n-1);
                k++;
            }
            return k;
    }
    void jg(int n)
    {
        int k;
            a[2]=1;
        a[3]=0;
        for(int i=4;i<=n;i++)
        {
            a[i]=i+1-pow(2,gs(i));
          // printf("%d ",a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=(a[i-1]+a[i])%N;
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        jg(n);
        printf("%d\n",a[n]%N);
    }
    

    方法2:

    #include<stdio.h>
     #include<string.h>
     #include<algorithm>
     using namespace std;
     const int MOD=10000000;
     int dp[3000010];
     int sum[3000010];
     void pp()
    {
        dp[0]=0;
        dp[1]=0;
        dp[2]=0;
        dp[3]=1;
        dp[4]=0;
        int x=4;
        int i;
       for( i=5;i<=3000001;i++)
        {    dp[i]=dp[i-x]*2+i-(i-x)*2;//每一行的规律
               dp[i]=dp[i]%MOD;
                if(i==x*2)
                    x=x*2;
        }
        sum[0]=0;
        for(i=0;i<=3000000;i++)//加和
            sum[i]=(dp[i+1]+sum[i-1])%MOD;
    }
    int main()
    {pp();
        int n;
        while(~scanf("%d",&n))
        {
            printf("%d\n",sum[n]);
        }
    }



    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

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

    余额充值