zoukankan      html  css  js  c++  java
  • BZOJ3209 花神的数论题

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

     

     

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

     

    Description

    背景
    众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
    描述
    话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
    花神的题目是这样的
    设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
    派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。

    Input

    一个正整数 N。

    Output

    一个数,答案模 10000007 的值。

    Sample Input

    3

    Sample Output

    2

    HINT

     对于样例一,1*1*2=2;

    数据范围与约定

    对于 100% 的数据,N≤10^15

     

     

     
    正解:数位$DP$+组合数
    解题报告:
      这是一道很有意思的数位$DP$+组合数学题。
      首先这道题的数位$DP$是按照二进制数位来的,与以往的数位$DP$有所不同。具体做法就是:先预处理出$60$以内的组合数(注意到$60$以内不会爆$long$ $long$),然后我们考虑,假设我已知了二进制位中有$x$个$1$的数有$a$个,那么有$x$个$1$的数的集合产生的贡献就应该是 $x^a$ 。所以我们可以考虑枚举有多少个$1$,然后通过组合数得到这样的数的个数。我们从高位往低位扫,当我们发现某一位是$1$时,我们分类讨论,假设这一位(不妨设为第$i$位)是$0$,那么后面无论怎么填都是合法的。而且我不妨从$1$到$i-1$枚举后面还有多少个$1$,假设后面还有$j$个$1$,设在第i位之前的高位已经有$k$个$1$了,那么满足条件的数就有$C[i-1][j]$种,贡献就是 $(j+k)^{C[i-1][j]}$。另外接着考虑这一位是$1$的情况,显然这种情况下应该留到后面去讨论,接着高位的$1$的个数$+1$,继续往下做。当然很容易发现这样做会漏掉一种情况,就是这一位为$1$,后面全是$0$的情况,并未讨论,在每一位补充进去即可。
     
     
    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const LL MOD = 10000007;
    LL n,C[120][120],ans;
    int cnt,k,a[120];
    inline LL fast_pow(LL x,LL y){ LL r=1; while(y>0) { if(y&1) r*=x,r%=MOD; x*=x; x%=MOD; y>>=1; } return r; } 
    inline void work(){
    	scanf("%lld",&n); while(n>0) { a[++cnt]=n&1; n>>=1; } C[0][0]=1; k=0; ans=1;
    	for(int i=1;i<=60;i++) { C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1]/*指数不能直接取模*/; }
    	for(int i=cnt;i>=1;i--) {
    		if(a[i]) {
    			ans*=(k+1); ans%=MOD;
    			for(int j=1;j<i;j++) ans*=fast_pow(k+j,C[i-1][j]),ans%=MOD;
    			//枚举i-1位到最低位中的1的个数j,则总共1的个数位j+k,同时出现次数就为C[i-1][j]
    			k++;//多了一个1
    		}
    	}
    	printf("%lld",ans);
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    PHP对象的遍历
    PHP对象的复制
    PHP面向对象之类的自动加载
    PHP面向对象之接口
    PHP面向对象之重载
    PHP面向对象之抽象类,抽象方法
    PHP面向对象之final关键字
    PHP面向对象之重写
    使用python操作word
    vc++使用cookie登录网站
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6235016.html
Copyright © 2011-2022 走看看