• BZOJ3209: 花神的数论题


    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

     
    注意二进制中1的个数不会很多,所以我们可以把问题转化成求1到N中有多少数在二进制下有k个1。
    发现这个条件后就是简单的数位DP了,设f[i][k]表示长度为i,含k个1且开头为0的数的个数,f[i][k]表示长度为i,含k个1且开头为1的数的个数。
    最后快速幂起来得到答案。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    typedef long long ll;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline ll read() {
        ll x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int mod=10000007;
    ll f[60][60],g[60][60];
    void init() {
        f[0][0]=g[0][1]=1;
        rep(len,0,58) rep(i,0,len+1) {
            g[len+1][i+1]+=f[len][i]+g[len][i];
            f[len+1][i]+=f[len][i]+g[len][i];
        }
    }
    int bit[60];
    ll ans[60];
    ll solve(ll x) {
        int len=0,cnt=0;
        while(x) bit[len++]=x&1,x>>=1;
        rep(i,0,len-2) rep(j,0,i+1) ans[j]+=g[i][j];
        dwn(i,len-1,0) {
            if(i!=len-1&&bit[i]) rep(k,0,i+1) ans[k+cnt]+=f[i][k];
            cnt+=bit[i];
        }
    }
    ll pow(int a,ll n) {
        if(!n) return 1;
        ll ans=pow(a,n>>1);(ans*=ans)%=mod;
        if(n&1) (ans*=a)%=mod;
        return ans;
    }
    int main() {
        init();solve(read()+1);ll res=1;
        rep(i,1,59) (res*=pow(i,ans[i]))%=mod;
        printf("%lld
    ",res);
        return 0;
    }
    View Code
  • 相关阅读:
    自动化测试基础
    appium环境搭建
    Typescript类型体操 Readonly
    Typescript类型体操 Tuple To Object
    Typescript类型体操 If
    Typescript类型体操 Length of Tuple
    Typescript类型体操 First of Array
    80篇国产数据库实操文档汇总(含TiDB、达梦、openGauss等)
    MySQL精品学习资源合集 | 含学习教程笔记、运维技巧、图书推荐
    居安思危,安全先行 | 7月《中国数据库行业分析报告》精彩概览!
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5043566.html
Copyright © 2020-2023  润新知