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

    题目大意:

    设 sum(i)表示i的二进制表示中1的个数

    给出一个正整数N,求是sum(1)—sum(N)的乘积

    思路:

    可以想到对sum的值求有多少个 然后快速幂

    枚举sum的值 使用数位dp

    每遇到一位1 则可以求出小于这位1所有的对于这个sum的组合数

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 200100 
    12 #define MOD 10000007
    13 using namespace std;
    14 inline ll read()
    15 {
    16     ll x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 ll n,c[80][80],g[80],cnt,ans;
    22 ll calc(int x)
    23 {
    24     ll res=0;
    25     for(int i=cnt;i&&x>=0&&i-1>=x;i--)
    26         if(g[i]) res+=c[i-1][x--];
    27     return res;
    28 }
    29 ll q_pow(ll bas,ll t)
    30 {
    31     ll res=1;
    32     for(;t;t>>=1,(bas*=bas)%=MOD)
    33         if(t&1) (res*=bas)%=MOD;
    34     return res;
    35 }
    36 int main()
    37 {
    38     n=read()+1,ans=1,c[0][0]=1;
    39     for(int i=1;i<=60;i++)
    40         for(int j=c[i][0]=1;j<=i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j];
    41     while(n) g[++cnt]=n&1,n>>=1;
    42     for(int i=1;i<=cnt;i++)
    43         (ans*=q_pow(i,calc(i)))%=MOD;
    44     printf("%lld
    ",ans);
    45 }
    View Code
  • 相关阅读:
    NAT(网络地址转换)
    go从文件中读取json字符串并转换
    实现守护进程
    c++ uconcontext.h实现协程
    bzoj 1085骑士精神
    在线代码评测机
    基于时间轮的定时器
    内存管理(一)
    二叉树的先序中序后序(非递归)
    RDD操作
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9868728.html
Copyright © 2011-2022 走看看