题意简介

没什么好说,就是让你求出 1 ~ n 之间每个数转化为二进制后 '1' 的个数,然后乘起来输出积

题目分析

emmmm.... 两种解法(同是 $O(\log^2 N)$ 的算法,组合数效率完爆 数位dp,当然是我自己的数位dp)。

  1. 组合数直接艹。(数据范围8e9 能过,其实这个东西你搞一搞 __int128 什么的再找个大质数也许也能过去啦)(好吧这个直接暴力预处理组合数的数组就好了)
  2. 老老实实数位dp。(可以AC)

于是翻车了...这么久

算法实现

1. 组合数 

组合数非常好做,只需要想想第 i 位为 1 的位上后面那一堆数字里面挑出 j 个数的方案就好了,注意加上 cnt ,然后最后快速幂累加一下答案,分分钟搞定

然后这里用了逆元处理组合数要预处理的阶乘,如果你还不会线性求逆元的话可以点这里

当然这里用逆元...就是作死...我们完全可以预处理出 50 * 50 的杨辉三角数组,存好组合数直接用

2.数位dp

...不就是枚举 1 的个数然后记忆化深搜么?hem...听起来完全没有组合数高级

代码实现

1.组合数

 1 //by Judge
 2 #include<iostream>
 3 #include<cstdio>
 4 #define ll long long
 5 using namespace std;
 6 const int M=55;
 7 const ll mod=1e7+7;
 8 ll n,len,cnt,ans=1;
 9 ll C[M][M],d[M],num[M];
10 inline void prep(){  //预处理组合数模板?
11     for(int i=0;i<=50;++i) C[i][0]=1;
12     for(int i=1,j;i<=50;++i) for(j=1;j<=50;++j)
13         C[i][j]=C[i-1][j]+C[i-1][j-1];
14 }
15 inline ll quick_pow(ll x,ll p,ll ans=1){  //快速幂模板?
16     while(p){
17         if(p&1) ans=ans*x%mod;
18         x=x*x%mod, p>>=1;
19     } return ans;
20 }
21 signed main(){
22     cin>>n,prep();
23     while(n) d[++len]=n&1,n>>=1;//转化二进制
24     for(ll i=len,j;i;--i) if(d[i]){
25         for(j=1;j<i;++j) //组合数就是随便乱艹的算法
26             num[cnt+j]+=C[i-1][j];
27         ++num[++cnt];
28     }
29     for(ll i=1;i<=len;++i) //直接累乘就好
30         ans=ans*quick_pow(i,num[i])%mod;
31     cout<<ans<<endl; return 0;
32 }

2.数位dp

 1 //by Judge
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #define ll long long
 6 using namespace std;
 7 const int M=55;
 8 const int mod=1e7+7;
 9 int cnt,x[M];
10 ll n,f[M][2][M][M],num[M];
11 inline ll quick_pow(ll x,ll p,ll ans=1){
12     while(p) (p&1) && (ans=ans*x%mod),x=x*x%mod, p>>=1;
13     return ans;
14 }
15 ll dp(int cur,int up,int tmp,int d){ //记忆化深搜,log^2 n 无压力
16     if(!cur) return tmp==d; //特判直接返回
17     if(~f[cur][up][tmp][d]) return f[cur][up][tmp][d]; // 已记忆,直接返回
18     int lim=up?x[cur]:1;
19     ll res=0;
20     for(int i=0;i<=lim;++i) //继续深搜
21         res+=dp(cur-1,up&&i==lim,tmp+(i==1),d);
22     return f[cur][up][tmp][d]=res; //记忆化
23 }
24 ll solv(){
25     while(n) x[++cnt]=n&1,n>>=1; //同上转化
26     for(int i=1;i<=50;++i)  //枚举要放入的 1 的位数
27         memset(f,-1,sizeof(f)),
28         num[i]=dp(cnt,1,0,i);
29     ll res=1;
30     for(int i=1;i<=50;++i) //累乘进答案
31         res=res*quick_pow(i,num[i])%mod;
32     return res;
33 }
34 signed main(){ cin>>n,cout<<solv()<<endl; return 0; }

转载于:https://www.cnblogs.com/Judge/p/9540939.html

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

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

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

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

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

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

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

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

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

  5. bzoj3209 花神的数论题——数位dp

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

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

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

  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. BZOJ3209(luogu 4317)花神的数论题题解

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

  9. bzoj 3209: 花神的数论题

    限于本人DP处于背包--水平,不组声(就是对神奇的数位DP,找出j个1的有多少个,然后j的多少个次方就行) 1 #include<bits/stdc++.h> 2 #define N 10 ...

最新文章

  1. Java程序员从笨鸟到菜鸟之(一百零九)一步一步学习webservice(三)开发第一个基于XFire的webservice
  2. ML之xgboost:利用xgboost算法(结合sklearn)训练mushroom蘑菇数据集(22+1,6513+1611)来预测蘑菇是否毒性(二分类预测)
  3. 迅为四核4418开发板MiniLinux-CAN总线测试使用文档
  4. 从ReadImage到ML- 一个不错的博客
  5. sh脚本学习之: sh脚本 、sed、awk
  6. 利用ACS来实现AAA服务
  7. DataTable.Compute功能
  8. 数据结构--栈--共享顺序栈
  9. java判断字符串中是否含有某个字符串
  10. 从汇编来看i++与++i
  11. 对九个超级程序员的采访
  12. HDMI设计9--Video Mixer IP
  13. android跳一跳作弊编程,跳一跳辅助器作弊刷分 微信跳一跳辅助工具(安卓/iOS苹果)-优基地...
  14. android动态权限依赖库,动态申请app权限:郭霖大神的PermissionX库带你告别原生
  15. OC作业- 图书馆管理系统
  16. 2021-09-07体脂秤模块用来做什么?开发八电极体脂秤方案
  17. 新华社 | 郭为:IT构架创新助力中国金融科技创新之路
  18. 考虑线程安全的List集合选择
  19. gta5 android版数据包,apk.gta5com数据包
  20. python数字转中文大写_python3 数字转人民币大写

热门文章

  1. java分别使用for循环语句计算n!_实验三:分别用for、while和do-while循环语句以及递归方法计算n!,并输出算式...
  2. mysql获取当前节点的所有叶子节点_mssql sqlserver 如何获取一个叶子节点下所有子节点呢?...
  3. 嵌入式 linux restful,嵌入式 RESTful 框架 express.java
  4. mysql防止误删除_mysql误删除处理方法
  5. pb mysql odbc_PB 连接Mysql ODBC/JDBC
  6. 集合在枚举数实例化后进行了修改_(编程知识)C# 枚举与位枚举
  7. 使用jquery调试ajax接口-2
  8. Linux 下修改hosts文件
  9. vue实现查询多条记录_sql:多表查询
  10. matlab充分利用性能,Matlab高性能编程——代码优化和并行计算