zoukankan      html  css  js  c++  java
  • 【bzoj3209】: 花神的数论题 数论-DP

    【bzoj3209】: 花神的数论题

    首先二进制数中1的个数最多就是64个

    设所有<=n的数里二进制中1的个数为i的有a[i]个

    那么答案就是

     然后快速幂

    求a[i]可以用DP

    设在二进制中从高到低考虑到第k位,第k位之前的1的个数是cnt,n总共有len位

    若第k位==1 那么 a[cnt+j]+=C(len-k,j) (j<=len-k)

    其实就是前k-1位都与n前k-1位相等,第k位为0,后len-k随意选择j个1时对a的贡献

     1 /* http://www.cnblogs.com/karl07/ */
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <algorithm>
     7 using namespace std;
     8 #define ll long long
     9 const ll p=10000007;
    10 ll n,len;
    11 ll c[65][65],a[65];
    12 
    13 ll Q_pow(ll x,ll y){
    14     ll ans=1;
    15     while (y){
    16         if (y&1) ans=ans*x%p;
    17         x=x*x%p;
    18         y=(y>>1);
    19     }
    20     return ans; 
    21 }
    22 
    23 int main(){
    24     scanf("%lld",&n);
    25     for (ll x=n;x;x=(x>>1)) len++;
    26     for (int i=0;i<len;i++){
    27         c[i][0]=c[i][i]=1;
    28         for (int j=1;j<i;j++){
    29             c[i][j]=c[i-1][j]+c[i-1][j-1];
    30         }
    31     }
    32     int cnt=0,ans=1;
    33     for (int i=len-1;i>=0;i--){
    34         if (((n>>i)&1)){
    35             for (int j=0;j<=i;j++){
    36                 a[j+cnt]+=c[i][j];
    37             }
    38             cnt++;
    39         }
    40     }
    41     a[cnt]++;
    42     for (int i=1;i<=len;i++){
    43         ans=ans*Q_pow(i,a[i])%p;
    44     }
    45     printf("%lld
    ",ans);
    46     return 0;
    47 }
    View Code

    感觉写的自己都看不懂

  • 相关阅读:
    linux中断处理浅析
    linux页面回收浅析
    linux线程同步浅析
    剖析一个由sendfile引发的linux内核BUG
    比memcpy更快的内存拷贝
    linux内核SMP负载均衡浅析
    sscanf,snprintf
    mysql中实现longblob数据流式读写
    sscanf
    substr复制字符串的一部分
  • 原文地址:https://www.cnblogs.com/karl07/p/6619507.html
Copyright © 2011-2022 走看看