zoukankan      html  css  js  c++  java
  • 天津--泥人张

    题目大意

    给定$m$,求$C_m^k (k in [0,m])$中被$4$整除的数的个数。($m le 10^{3000}$)取自$CGMO2012 P8$。

    关于 $4$

    显然,$4$可以分解成$2^2$,也就是说,如果一个数包含的4的方幂大于等于2,那么这个数就能被4整除。

    关于组合数

    对于一个组合数$C_m^k$,它的公式是$C_m^k = frac {m!}{k!cdot(m-k)!}$。

    判定组合数被$4$整除

    如果我们统计$F_i$表示$i!$含有$2$的方幂的个数,那么$C_m^k$含有2的方幂的个数为$F_{m} - F_{k} - F_{m - k}$,$C_m^k$被$4$整除当且仅当$F_{m} - F_{k} - F_{m - k} ge 2$(为$0$表示组合数为奇数,为$1$表示组合数是偶数但不被$4$整除)。

    $F_x$的求值

    因为$x!$是$1~x$的乘积,所以在$1~x$中,每个被$2$整除的数对$F_x$都有$1$的贡献;而每个被$4$整除的数额外又有$1$的贡献,以此类推。所以得到$F_x = sum_{i=1}^{infty} {lfloor frac{n}{2^i} floor}$。

    将$x$写成二进制格式$(a_pa_{p-1}...a_0)_2$,用$s(x)$表示$x$在二进制表达下各个位置的数的和(即$1$的个数),那么公式可以写成:

    [egin{array}&F_x &=& (a_pa_{p-1}…a_1)_2 + (a_pa_{p-1}…a_2)_2 + … + (a_p)_2 + 0 \ &=& (a_p cdot 2^{p-1} + a_{p-1} cdot 2^{p-2} + … + a_1 cdot 2^0) + (a_p cdot 2^{p-2} + a_{p-3} cdot 2^{p-2} + … + a_2 cdot 2^0) + … + (a_p cdot 2^0) \ &=& a_p cdot (2^{p-1} + 2^{p-2} + … + 1) + a_{p-1} cdot (2^{p-2} + 2^{p-3} + … + 1 ) + … + (a_1 cdot 1) + (a_0 cdot 0) \ &=& a_pcdot(2^p-1) + a_{p-1} cdot (2^{p-1} - 1) + … + a_0 cdot (2^0-1) \ &=& (a_pcdot2^p+a_{p-1}cdot2^{p-1}+…+a_0cdot2^0)-(a_p+a_{p-1}+…+a_0) \ &=& x - s(x) end{array}]

    $4$的倍数的个数

    为了方便计算,我们将$C_m^k$写成$C_{k+b}^k$,那么得到$C_{k+b}^k = frac {(k+b)!} {k!cdot b!}$,所以组合数需要满足

    [egin{array}&F_{k+b} - F_{k} - F_{b} &ge& 2 end{array}]

    接下来将不合法的分情况讨论,当$F_{k+b} - F_{k} - F_{b} = 0$时:

    [egin{aligned} F_{k+b} - F_{k} - F_{b} &= 0 \k+b-s(k+b) &= k-s(k)+b-s(b) \s(k+b) &= s(k)+s(b) end{aligned}]

    根据二进制加法进位的特征,如果两个数$k$和$b$相加出现了进位,那么必然有$s(k+b) lt s(k) + s(b)$。

    所以当$s(k+b) = s(k) + s(b)$时,$k+b$必然不进位,即在二进制表达下$k$和$b$的$1$是错开的,同时$k+b=m$是确定的,对于$k$,每个位置上的$1$可以选择取或不取,所以合法的$k$的个数为$2^{s(k+b)}$。

    当$F_{k+b} - F_{k} - F_{b} = 1$时:

    [egin{aligned} F_{k+b} - F_{k} - F_{b} &= 1 \k+b-s(k+b) &= k-s(k)+b-s(b) + 1 \s(k+b) &= s(k)+s(b) - 1 end{aligned}]

    与第一种情况类似,若出现$s(k+b) = s(k) + s(b) - 1$,则说明$k+b$出现了进位,且只进位$1$次,即$(01)_2+(01)_2=(10)_2$。

    设$k+b$在二进制表达下出现相邻的$1$和$0$(且$1$在$0$前面)的次数为$t$。因为只进位$1$次,所以先选择某一对$(10)_2$,将其忽略,那么剩下的就都不进位,同第一种情况。所以k的个数为$t cdot 2^{s(k+b)-1}$。

    综上所述,排除掉两种不合法的情况,剩下的就是组合数中$4$的倍数的个数,即$m + 1 - 2^{s(m)} - t cdot 2^{s(m)-1}$。

    代码嘛,暂时没有。

  • 相关阅读:
    设计模式之八:外观模式(Facade)
    Python模块学习笔记— —time与datatime
    Android加载图片OOM错误解决方式
    [C#]Attribute特性(2)——方法的特性及特性参数
    [C#]Attribute特性
    [Winform]一个简单的账户管理工具
    [C#]AES加密算法实现
    [C#基础]ref和out的区别
    [Socket网络编程]一个封锁操作被对 WSACancelBlockingCall 的调用中断。
    [Socket网络编程]由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
  • 原文地址:https://www.cnblogs.com/lightning34/p/4584203.html
Copyright © 2011-2022 走看看