题目大意:

花神的题目是这样的 设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你 派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。

要对10000007(非质数)取模

n<=10^15

分析:

O(nlogn)暴力显然可以想出来。显然会tle

这是从1~n一个一个枚举并变成二进制算的,但是我们是否可以向普通的数位dp,一次性枚举许多个数呢?

二进制的n,大概最多50位。例如21=10101.它显然可以拆成二进制下的10000+100+1

那么,我们是否可以尝试着去先算出来1~10..0的sum乘积?

假设这是一个n位数,也就是有n-1个零

考虑只有一个1的数字个数,C(n,1),即,在n个位置上,取1个位置变成1的方案数。那么,sum[i]=1的数的贡献就是1^c(n,1)

只有二个1,C(n-1,2),注意,是n-1位,因为除了特殊的10..000之外,其他的数都只有n-1个位置可放1。同理,sum[i]=2的数的贡献就是2^c(n-1,2),因为本身就是连乘嘛,交换律结合律就先把不同个数的数所做的贡献乘起来。

三个1同理。

……

以21=10101为例,这样我们可以切掉n的第一个10000以下的方案。

现在我们要处理10001~10100的方案数,我们仍然可以利用刚才处理100的思路,

只是,放一个1在最后的三位,必然每次都要加上之前已经有过的那一个1(10000),所以,是2^c(3,1)

2个1同理,是3^c(2,2)

这样,就解决问题了。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10000007;
ll ans=1;
ll sum;
ll wei;
ll c[52][52];
ll n;
ll qm(ll x,ll y)
{ll ret=1,base=x;while(y){if(y&1) ret=(ret*base)%mod;base=(base*base)%mod;y>>=1;}return ret;
}
int main()
{c[0][0]=1;for(int i=1;i<=50;i++){c[i][0]=1;for(int j=1;j<=50;j++)c[i][j]=c[i-1][j-1]+c[i-1][j];}//直接打表就好,//注意,组合数将作为指数部分,不能取模 C(50,25)long long也开的下,scanf("%lld",&n);wei=0;sum=0;//sum,已经处理出来的之前的1的个数 for(wei=50;wei>=1;wei--)//按位枚举
    {if(n&((ll)1<<wei-1)){ans=(ans*qm(sum+1,wei))%mod;//处理1个的特殊情况 for(int k=sum+2,s=2;k<=sum+wei-1;k++,s++){ans=(ans*qm(k,c[wei-1][s]))%mod;}sum++;        }}printf("%lld",ans);return 0;
}

总结:

数位dp的最初思想的来源,就是利用整千,整万,整十万的整齐特殊性质,可以利用可以想到的数学方法,对枚举进行大幅的简化,直接减少到O(logn)

这个题其实算是数位dp的裸题,还是比较常规的。

对于其他的符合规定的第k小的数(启示录),是先预处理整位的情况,再按位枚举,考虑每个数能填几,从而类似康拓展开,找到第k小的数。

或者[l,r]区间内多少个满足限制的数,前缀和思想,求l-1以内,再求r以内做差就好。

转载于:https://www.cnblogs.com/Miracevin/p/9090196.html

bzoj3209 花神的数论题——数位dp相关推荐

  1. bzoj 3209 花神的数论题 —— 数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 算是挺简单的数位DP吧,但还是花了好久才弄明白... 又参考了博客:https://b ...

  2. 数据范围BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了)

    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! 3209: 花神的数论题 Time Limit: 10 Sec Memory ...

  3. 2018.10.27 bzoj3209: 花神的数论题(数位dp)

    传送门 数位dpdpdp经典题. 题面已经暗示了我们按照二进制位来数位dpdpdp. 直接dpdpdp多少个数有111个111,222个111,333个111-, 然后快速幂算就行了. 于是我们枚举前 ...

  4. [数位dp] bzoj 3209 花神的数论题

    [数位dp] bzoj 3209 花神的数论题 题意:中文题. 思路:和普通数位dp一样,这里转换成二进制,然后记录有几个一. 统计的时候乘起来就好了. 代码: #include"cstdl ...

  5. bzoj3209:3209: 花神的数论题

    觉得还是数位dp的那种解题形式但是没有认真的想,一下子就看题解.其实还是设置状态转移.一定要多思考啊 f[i][j]=f[i-1][j]+g[i-1][j] g[i][j]=f[i-1][j-1]+g ...

  6. bzoj 3209: 花神的数论题 喵哈哈村的秘境探险(四)

    3209: 花神的数论题 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2169  Solved: 1006 [Submit][Status][Di ...

  7. #数位dp#洛谷 4317 花神的数论题

    感谢dalao@小粉兔的帮助 dalao's 博客园,dalao's 洛谷博客 题目 设f[i]f[i]f[i]表示iii转化为二进制后1的个数,求∏i=1nf[i]\prod_{i=1}^nf[i] ...

  8. 花神的数论题(这题...哎。数位dp咋就这么 not naive 呢)

    题意简介 没什么好说,就是让你求出 1 ~ n 之间每个数转化为二进制后 '1' 的个数,然后乘起来输出积 题目分析 emmmm.... 两种解法(同是 $O(\log^2 N)$ 的算法,组合数效率 ...

  9. BZOJ3209(luogu 4317)花神的数论题题解

    题目 设 sum(i) 表示 i 的二进制表示中 1 的个数.给出一个正整数 N ,花神要问你 派(Sum(i)),也就是 sum(1)-sum(N) 的乘积(n<=1e15). 分析 好吧,一 ...

最新文章

  1. Python中的find()
  2. 多分类任务的混淆矩阵
  3. 亚马逊正发力人工智能
  4. RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较
  5. C++primer CH12智能指针
  6. ArrayList理解(5)与vector区别
  7. [C/C++]堆栈的概念与区别
  8. 局域网服务器传输大文件方案,局域网快速传输大文件【操作方案】
  9. 明月浩空html播放器,明月浩空音乐-绚丽彩虹|HTML5网站音乐播放器源码带后台-仅研究学习...
  10. java前后端分离开发思路
  11. 【小白】关于启动gazebo仿真环境和elevation_mapping中一些小问题
  12. MySQL中的auto_increment
  13. python 保存数据单文件_python3.6 单文件爬虫 断点续存 普通版 文件续存方式
  14. ora-12505 监听程序当前无法识别sid
  15. google::protobuf::Closure::Run
  16. JavaScript百炼成仙 1.15 天秀
  17. X61t安装Ubuntu后平板导航键失效解决方法
  18. VSCode + CMakeList
  19. Shopify Liquid 日期
  20. 无人机超远距离WiFi传输,CV5200无线通信模组,无线音视频传输方案

热门文章

  1. java GC垃圾回收
  2. 编译错误: Too much data space used by DLL's in MODULES section
  3. 如何看公司的财务数据
  4. ubuntu12.04循环登录,无法进桌面的问题。
  5. 用GDB调试程序(10)──查看运行时数据(1)-转
  6. 蓝桥杯 ALGO-67 算法训练 最大值与最小值的计算
  7. 《MarkDown》语法笔记
  8. Mongodb亿级数据量的性能测试
  9. Nginx 配置文件详细说明
  10. linux下安装tuxedo