题意简介

没什么好说,就是让你求出 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.组合数

 //by Judge
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const int M=;
const ll mod=1e7+;
ll n,len,cnt,ans=;
ll C[M][M],d[M],num[M];
inline void prep(){ //预处理组合数模板?
for(int i=;i<=;++i) C[i][]=;
for(int i=,j;i<=;++i) for(j=;j<=;++j)
C[i][j]=C[i-][j]+C[i-][j-];
}
inline ll quick_pow(ll x,ll p,ll ans=){ //快速幂模板?
while(p){
if(p&) ans=ans*x%mod;
x=x*x%mod, p>>=;
} return ans;
}
signed main(){
cin>>n,prep();
while(n) d[++len]=n&,n>>=;//转化二进制
for(ll i=len,j;i;--i) if(d[i]){
for(j=;j<i;++j) //组合数就是随便乱艹的算法
num[cnt+j]+=C[i-][j];
++num[++cnt];
}
for(ll i=;i<=len;++i) //直接累乘就好
ans=ans*quick_pow(i,num[i])%mod;
cout<<ans<<endl; return ;
}

2.数位dp

 //by Judge
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int M=;
const int mod=1e7+;
int cnt,x[M];
ll n,f[M][][M][M],num[M];
inline ll quick_pow(ll x,ll p,ll ans=){
while(p) (p&) && (ans=ans*x%mod),x=x*x%mod, p>>=;
return ans;
}
ll dp(int cur,int up,int tmp,int d){ //记忆化深搜,log^2 n 无压力
if(!cur) return tmp==d; //特判直接返回
if(~f[cur][up][tmp][d]) return f[cur][up][tmp][d]; // 已记忆,直接返回
int lim=up?x[cur]:;
ll res=;
for(int i=;i<=lim;++i) //继续深搜
res+=dp(cur-,up&&i==lim,tmp+(i==),d);
return f[cur][up][tmp][d]=res; //记忆化
}
ll solv(){
while(n) x[++cnt]=n&,n>>=; //同上转化
for(int i=;i<=;++i) //枚举要放入的 1 的位数
memset(f,-,sizeof(f)),
num[i]=dp(cnt,,,i);
ll res=;
for(int i=;i<=;++i) //累乘进答案
res=res*quick_pow(i,num[i])%mod;
return res;
}
signed main(){ cin>>n,cout<<solv()<<endl; return ; }

花神的数论题(这题...哎。数位dp咋就这么 not naive 呢)的更多相关文章

  1. bzoj 3209 花神的数论题——二进制下的数位dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 可以枚举 “1的个数是...的数有多少个” ,然后就是用组合数算在多少位里选几个1. ...

  2. 【洛谷】4317:花神的数论题【数位DP】

    P4317 花神的数论题 题目背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 题目描述 话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我 ...

  3. 【BZOJ3209】花神的数论题 数位DP

    [BZOJ3209]花神的数论题 Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级 ...

  4. [Bzoj3209]花神的数论题(数位dp)

    3209: 花神的数论题 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2633  Solved: 1182[Submit][Status][Disc ...

  5. BZOJ_3209_花神的数论题_组合数+数位DP

    BZOJ_3209_花神的数论题_组合数+数位DP Description 背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 描述 话说花神这天又 ...

  6. [bzoj3209]花神的数论题_数位dp

    花神的数论题 bzoj-3209 题目大意:sum(i)表示i的二进制表示中1的个数,求$\prod\limits_{i=1}^n sum(i)$ 注释:$1\le n\le 10^{15}$. 想法 ...

  7. BZOJ3209: 花神的数论题(数位DP)

    题目: 3209: 花神的数论题 解析: 二进制的数位DP 因为\([1,n]\)中每一个数对应的二进制数是唯一的,我们枚举\(1\)的个数\(k\),计算有多少个数的二进制中有\(k\)个\(1\) ...

  8. BZOJ 3209: 花神的数论题 [数位DP]

    3209: 花神的数论题 题意:求\(1到n\le 10^{15}\)二进制1的个数的乘积,取模1e7+7 二进制最多50位,我们统计每种1的个数的数的个数,快速幂再乘起来就行了 裸数位DP..\(f ...

  9. BZOJ3209 花神的数论题 【组合数学+数位DP+快速幂】*

    BZOJ3209 花神的数论题 Description 背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 描述 话说花神这天又来讲课了.课后照例有 ...

  10. 【数位DP】【P4317】花神的数论题

    [数位DP][P4317]花神的数论题 Description 给定 \(n\),求 \(n\) 以内所有正整数二进制下 \(1\) 的个数的乘积,答案对 \(10^7 + 7\) 取模 Limita ...

随机推荐

  1. Windows Azure中国版试用

    Winodws Azure刚出来那会都没怎么关注,就在一些网页新闻上见过一些报道,之前阿里云在博客里搞过推广,拿什么豆可以换,当时也就是看了一下没去用过. 有次在一群里别人说Windows Azure ...

  2. chart.js angular组件封装(ng6)、实战配置、插件编写

    前言 项目需要使用chart.js插件,由于项目是使用angular开发,那么我第一步就是先把chart.js改造成angular组件来使用. 本项目代码都可以在github上下载:项目git地址 a ...

  3. CorelDrawX8安装时提示已安装另一个版本

    (1)首先卸载VIsualC++ 2015 运行库. (2)如果有VisualC++ 2017运行库,卸载VisualC++2017运行库,即可.

  4. JDK8新特性03 Lambda表达式03_Java8 内置的四大核心函数式接口

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.functio ...

  5. SQL Server Management Studio 使用技巧

    Ø  前言 本文主要介绍 SQL Server Management Studio 工具的使用,相信很多开发人员都比较熟悉此工具,特别是做 C# 开发的程序员,基本上都会经常使用该工具,当然也可以使用 ...

  6. MVC异步AJAX的三种方法(JQuery的Get方法、JQuery的Post方法和微软自带的异步方法)

    异步是我们在网站开发过程中必不可少的方法,MVC框架的异步方法也有很多,这里介绍三种方法: 一.JQuery的Get方法 view @{ Layout = null; } <!DOCTYPE h ...

  7. leetcode 90. subsets

    解题思路: 要生成子集,对于vector 中的每个数,对于每个子集有两种情况,加入或不加入. 因此代码: class Solution { public: void subsetG(vector< ...

  8. day 3 - 2 数据类型练习

    1.有变量 name = " aleX leNB " 完成如下操作 name = " aleX leNB " # 1) 移除两端空格n1 = name.stri ...

  9. CentOS6.8合并DVD1和DVD2作为本地yum源

    转载自:http://www.study365.org/blog/45.html CentOS一般都会提供DVD1和DVD2两个镜像文件,形如CentOS-6.8-x86_64-bin-DVD1.is ...

  10. A - Brackets POJ - 2955 (区间DP模板题)

    题目链接:https://cn.vjudge.net/contest/276243#problem/A 题目大意:给你一个字符串,让你求出字符串的最长匹配子串. 具体思路:三个for循环暴力,对于一个 ...