zoukankan      html  css  js  c++  java
  • csu1021: 组合数末尾的零

    C(mn) = m!/((n)!n!) 

    将组合数C(mn)写成二进制数,这个二进制数末尾有多少个零?

    *  自然数可以进行质因数分解,质因子2的指数即相应二进制末尾零的个数;

        将各个数二进制末尾0的个数累加,得到阶乘数末尾0的个数。

    优化:

    # include <stdio.h>
    int f[] = {0,1,3,7,15,31,63,127,255,511};
    int main(){
    int T, m, n, i, ans;
    scanf("%d", &T);
    while (T-- > 0){
    ans = 0;
    scanf("%d%d", &m, &n);
    for(i=0; i<10; ++i){
    if (m>>i & 0x1)ans += f[i];
    if (n>>i & 0x1)ans -= f[i];
    if ((m-n)>>i & 0x1)ans -= f[i];
    }
    printf("%d\n", ans);
    }
    return 0;
    }

    更新:2012/3/12

    又翻了翻编程之美,看到一个求 N 的阶乘末尾 0 的个数是转化成:N - N 的二进制表示中 1 的个数;

    组合数可以化为阶乘相除的形式;

    而正整数 N 的二进制表示中 1 的个数可以用 log2(N) 的方法得到,于是有了下面的:

     1 /*csu 1021*/
    2 # include <stdio.h>
    3
    4 int cnt(int n);
    5
    6 int main()
    7 {
    8 int T, m, n;
    9
    10 scanf("%d", &T);
    11 while (T-- && scanf("%d%d", &m, &n))
    12 printf("%d\n", cnt(m-n)+cnt(n)-cnt(m)); // 稍作计算得到
    13
    14 return 0;
    15 }
    16
    17 int cnt(int n)
    18 {
    19 int c = 0;
    20 while (n)
    21 {
    22 n &= (n-1);
    23 ++c;
    24 }
    25 return c;
    26 }

    相比之前加表的方法各有千秋。。OJ显示的耗时都是16ms。

  • 相关阅读:
    负载均衡
    二叉树反转
    hashMap 和红黑树
    linux c++ 服务器编程,收藏一个测试例子
    某某音乐盒面试
    Linux中的文件i节点
    linux 文件格式压缩
    类string的构造函数、拷贝构造函数和析构函数
    计算二叉树的深度
    string转换为decimal
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2356487.html
Copyright © 2011-2022 走看看