zoukankan      html  css  js  c++  java
  • BZOJ 3209: 花神的数论题【数位dp】

    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,计算小于n并且sum(i)=k的i有多少个,设为u,则答案为pow(k,u),然后枚举k即可

    #include<cstdio>

    #include<iostream>

    #include<cstring>

    #include<map>

    #define maxn 1000005

    #define MOD 10000007

    using namespace std;

    long long num[maxn],h=0,dp[100][100][100][2];

    long long dfs(long long pos,long long need,long long now,long long limit)

    {

        if(pos==0)return now==need;

        int tmp=limit?num[pos]:1;

        long long ans=0;

        if(!limit&&dp[pos][need][now][limit]!=-1)

            return dp[pos][need][now][limit];

        for(int i=0;i<=tmp;i++)

        {

            ans=(ans+dfs(pos-1,need,now+i,limit&&(i==tmp)));

        }

        if (!limit)

            dp[pos][need][now][limit]=ans;

        return ans;

    }

    long long mpow(long long a,long long n)

    {

        long long ans=1;

        a%=MOD;

        while (n)

        {

            if (n%2) ans=(ans%MOD)*(a%MOD)%MOD;

            n/=2;

            a=(a%MOD)*(a%MOD)%MOD;

        }

        return ans;

    }

    int main()

    {

        long long n;

        memset(dp,-1,sizeof(dp));

        while(scanf("%lld",&n)!=EOF)

        {

            long long ans=1;h=0;

            if(n==0){printf("0 ");continue;}

            while(n>0){num[++h]=n&1;n>>=1;}

            for(int i=1;i<=h;i++)

            {

                long long u=dfs(h,i,0,1);

                long long v=mpow((long long)i,u%9988440+9988440);

                ans=((ans%MOD)*(v%MOD))%MOD;

                if(ans==6296768)

                {

                    int zz=1;

                }

            }

            printf("%lld ",ans);

        }

        return 0;

    }

  • 相关阅读:
    程序员修炼之道阅读笔记02
    第十五周课堂练习-查找最长单词链
    文件读写总结
    第十五周
    暑假总结1
    软件工程课程总结
    第十六周总结
    用户场景分析
    学期课后个人总结
    第十五周总结
  • 原文地址:https://www.cnblogs.com/philippica/p/4189281.html
Copyright © 2011-2022 走看看