bzoj3209 花神的数论题——数位dp
题目大意:
花神的题目是这样的 设 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=;
ll ans=;
ll sum;
ll wei;
ll c[][];
ll n;
ll qm(ll x,ll y)
{
ll ret=,base=x;
while(y)
{
if(y&) ret=(ret*base)%mod;
base=(base*base)%mod;
y>>=;
}
return ret;
}
int main()
{
c[][]=;
for(int i=;i<=;i++)
{
c[i][]=;
for(int j=;j<=;j++)
c[i][j]=c[i-][j-]+c[i-][j];
}//直接打表就好,
//注意,组合数将作为指数部分,不能取模 C(50,25)long long也开的下,
scanf("%lld",&n);
wei=;sum=;//sum,已经处理出来的之前的1的个数
for(wei=;wei>=;wei--)//按位枚举
{
if(n&((ll)<<wei-))
{
ans=(ans*qm(sum+,wei))%mod;//处理1个的特殊情况
for(int k=sum+,s=;k<=sum+wei-;k++,s++)
{
ans=(ans*qm(k,c[wei-][s]))%mod;
}
sum++;
}
}
printf("%lld",ans);
return ;
}
总结:
数位dp的最初思想的来源,就是利用整千,整万,整十万的整齐特殊性质,可以利用可以想到的数学方法,对枚举进行大幅的简化,直接减少到O(logn)
这个题其实算是数位dp的裸题,还是比较常规的。
对于其他的符合规定的第k小的数(启示录),是先预处理整位的情况,再按位枚举,考虑每个数能填几,从而类似康拓展开,找到第k小的数。
或者[l,r]区间内多少个满足限制的数,前缀和思想,求l-1以内,再求r以内做差就好。
bzoj3209 花神的数论题——数位dp的更多相关文章
- BZOJ3209: 花神的数论题(数位DP)
题目: 3209: 花神的数论题 解析: 二进制的数位DP 因为\([1,n]\)中每一个数对应的二进制数是唯一的,我们枚举\(1\)的个数\(k\),计算有多少个数的二进制中有\(k\)个\(1\) ...
- [bzoj3209][花神的数论题] (数位dp+费马小定理)
Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...
- 【BZOJ3209】花神的数论题 数位DP
[BZOJ3209]花神的数论题 Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级 ...
- BZOJ 3209: 花神的数论题 [数位DP]
3209: 花神的数论题 题意:求\(1到n\le 10^{15}\)二进制1的个数的乘积,取模1e7+7 二进制最多50位,我们统计每种1的个数的数的个数,快速幂再乘起来就行了 裸数位DP..\(f ...
- BZOJ 3209 花神的数论题 数位DP+数论
题目大意:令Sum(i)为i在二进制下1的个数 求∏(1<=i<=n)Sum(i) 一道非常easy的数位DP 首先我们打表打出组合数 然后利用数位DP统计出二进制下1的个数为x的数的数量 ...
- bzoj 3209 花神的数论题 —— 数位DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 算是挺简单的数位DP吧,但还是花了好久才弄明白... 又参考了博客:https://b ...
- 洛谷$ P$4317 花神的数论题 数位$dp$
正解:数位$dp$ 解题报告: 传送门! 开始看到感觉有些新奇鸭,仔细一想发现还是个板子鸭,,, 考虑设$f_{i}$表示$sum[j]=i$的$j$的个数 日常考虑$dfs$呗,考虑变量要设哪些$Q ...
- 花神的数论题(数位dp)
规定sum[i] 为i里面含1的个数 ,求从1-N sum[i]的乘积. 数为64位内的,也就是sum[i]<=64的,这样可以dp求出1-N中含k个1的数有多少个,快速幂一下就可以了. 有个地 ...
- BZOJ3209 花神的数论题 【组合数学+数位DP+快速幂】*
BZOJ3209 花神的数论题 Description 背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 描述 话说花神这天又来讲课了.课后照例有 ...
随机推荐
- REST-framework快速构建API--生成Swagger接口文档
一.Swagger概述 1.引言 当接口开发完成,紧接着需要编写接口文档.传统的接口文档使用Word编写,or一些接口文档管理平台进行编写,但此类接口文档维护更新比较麻烦,每次接口有变更,需要手动修改 ...
- swap函数
#include<iostream> using namespace std; void swap(int& a,int& b){ int t=a; a=b; b=t; } ...
- #个人博客作业Week1——浏览教材后提出的六个问题及软件与软件工程的提出。
1.通常,我们阅读软件比编写软件花费的时间更多.正因为编写软件比阅读软件要容易,因此代码的可读性显得尤为重要.那么我们在写程序时应该如何避免多余的,带有误导性的注释,写出一个利于帮助别人读懂程序的注释 ...
- LINUX内核设计第五周——扒开系统调用的三层皮(下)
- [ERROR] Failed to execute goal org.codehaus.mojo:gwt-maven-plugin:2.5.0-rc1:compile (default) on project zeus-web: Command 解决
在编译maven项目,打包maven packeage -Dmaven.test.skip=TRUE时,报错“[ERROR] Failed to execute goal org.codehaus.m ...
- 《面向对象程序设计》第三次作业 Calculator
c++第三次作业 Calculator git上的作业展示点这里. ps:有一点不是很明确,作业要求:将数字和符号提取出来,得到一组string,然后才将这些string存入队列中.按我的理解是需要将 ...
- <面向对象程序设计>课程作业一
Github链接 在看完这次的作业要求后我整个人是混乱的,因为作业要求把不同的函数放在一个main函数中:我们之前也是进行了函数分离,但是是放在了不同的文件中.如果要改的话相当于重写(而且这两种形式其 ...
- Find Amir CodeForces - 805C (贪心+思维)
A few years ago Sajjad left his school and register to another one due to security reasons. Now he w ...
- 深入理解nodejs的next函数。koa的使用 app.params的使用
next就是一个递归函数 const Koa = require('koa'); const app = new Koa(); app.use(ctx => { ctx.body = 'Hell ...
- ionic2中如何使用自动生成器
ionic generator是命令行的功能,ionic2自动帮我们创建应用程序,从而节省了大量的时间,并增加我们的速度来开发一个项目的关键部分. ionic generator使我们可以自动创建以下 ...