Description

一个数x各个数位上的数之积记为\(f(x)\) <不含前导零>

求[L,R)中满足\(0<f(x)<=n\)的数的个数

solution

最后\(f(x)\)可以拆分成2,3,5,7的乘积,我们就将 \(2,3,5,7\) 压进状态,然后就是基础的数位DP,分是否严格小于两种状态转移即可

具体实现需要一些技巧:

预处理出每一个数含有 \(2,3,5,7\)的个数

预处理出 \(2,3,5,7\) 的幂,方便剪枝

注意数字不能含有 \(0\),我们每DP一位,要新加入 \([1,9]\) 的状态,即前导零的情况

还有一种解法是用 \(map\) 压乘积,网上大部分都是这么做的,也能通过,且简洁很多

tips:代码实现比较简单,但我已不想再多看一眼我的代码....

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=36;
typedef long long ll;
int m,lim[6],pri[6]={0,2,3,5,7};ll f[21][2][33][21][15][13];
char S[22];
ll m5[N],m2[N],m7[N],m3[N];int v[15][6];
ll solve(int *a,int n){
if(n==1){
int ret=0;
for(int i=1;i<a[1];i++)ret+=(i<=m);
return ret;
}
ll x,mu;memset(f,0,sizeof(f));
for(int i=1;i<n;i++){
if(i==1)for(int j=1;j<=a[i];j++)
f[i][j<a[i]][v[j][1]][v[j][2]][v[j][3]][v[j][4]]++;
else for(int j=1;j<=9;j++)
f[i][1][v[j][1]][v[j][2]][v[j][3]][v[j][4]]++;
for(int j=0;j<=lim[1];j++){
if(m2[j]<=m)
for(int k=0;k<=lim[2];k++){
if(m2[j]*m3[k]<=m)
for(int g=0;g<=lim[3];g++){
if(m2[j]*m3[k]*m5[g]<=m)
for(int b=0;b<=lim[4];b++){
mu=m2[j]*m3[k]*m5[g]*m7[b];
if(mu>m)break;
x=f[i][1][j][k][g][b];
if(x)
for(int d=1;d<=9 && mu*d<=m;d++)
f[i+1][1][j+v[d][1]][k+v[d][2]][g+v[d][3]][b+v[d][4]]+=x;
x=f[i][0][j][k][g][b];if(!x)continue;
for(int d=1;d<=a[i+1] && mu*d<=m;d++)
f[i+1][d<a[i+1]][j+v[d][1]][k+v[d][2]][g+v[d][3]][b+v[d][4]]+=x;
}
}
}
}
}
for(int i=n;i<=n;i++)
for(int j=1;j<=9;j++)
f[i][1][v[j][1]][v[j][2]][v[j][3]][v[j][4]]++;
ll ret=0;
for(int j=0;j<=lim[1];j++)
if(m2[j]<=m)
for(int k=0;k<=lim[2];k++)
if(m3[k]*m2[j]<=m)
for(int g=0;g<=lim[3];g++)
if(m2[j]*m3[k]*m5[g]<=m)
for(int b=0;b<=lim[4];b++){
if(m2[j]*m3[k]*m5[g]*m7[b]>m)break;
ret+=f[n][1][j][k][g][b];
}
return ret;
}
int s1[22],s2[22],l1,l2;
void work()
{
scanf("%d",&m);
for(int i=1;i<=4;i++)lim[i]=log(m+1)/log(pri[i]);
m2[0]=1;for(int i=1;i<=lim[1];i++)m2[i]=m2[i-1]<<1;
m3[0]=1;for(int i=1;i<=lim[2];i++)m3[i]=m3[i-1]*3;
m5[0]=1;for(int i=1;i<=lim[3];i++)m5[i]=m5[i-1]*5;
m7[0]=1;for(int i=1;i<=lim[4];i++)m7[i]=m7[i-1]*7;
v[2][1]=1;v[3][2]=1;v[4][1]=2;v[6][1]=1;v[6][2]=1;
v[5][3]=1;v[7][4]=1;v[8][1]=3;v[9][2]=2; scanf("%s",S+1);l1=strlen(S+1);
for(int i=1;i<=l1;i++)s1[i]=S[i]-'0';
scanf("%s",S+1);l2=strlen(S+1);
for(int i=1;i<=l2;i++)s2[i]=S[i]-'0';
ll ans=solve(s2,l2)-solve(s1,l1);
printf("%lld\n",ans);
} int main()
{
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
work();
return 0;
}

bzoj 3679: 数字之积的更多相关文章

  1. BZOJ 3679 数字之积 数位DP

    思路:数位DP 提交:\(2\)次 错因:进行下一层\(dfs\)时的状态转移出错 题解: 还是记忆化搜索就行,但是要用\(map\)记忆化. 见代码 #include<cstdio> # ...

  2. 【BZOJ3679】数字之积 DFS+DP

    [BZOJ3679]数字之积 Description 一个数x各个数位上的数之积记为f(x) <不含前导零>求[L,R)中满足0<f(x)<=n的数的个数 Input 第一行一 ...

  3. Bzoj 2154: Crash的数字表格(积性函数)

    2154: Crash的数字表格 Time Limit: 20 Sec Memory Limit: 259 MB Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least ...

  4. BZOJ 4816 数字表格

    首先是惯例的吐槽.SDOI题目名称是一个循环,题目内容也是一个循环,基本上过几年就把之前的题目换成另一个名字出出来,喜大普奔亦可赛艇.学长说考SDOI可以考出联赛分数,%%%. 下面放解题报告.并不喜 ...

  5. [BZOJ 1833] 数字计数

    Link: BZOJ 1833 传送门 Solution: 比较明显的数位DP 先预处理出1~9和包括前导0的0的个数:$pre[i]=pre[i-1]*10+10^{digit-1}$ (可以分为首 ...

  6. BZOJ3679 : 数字之积

    设f[i][p2][p3][p5][p7][j][k]表示前i位,2,3,5,7的次数,前i位是否等于x,是否有数字的方案数 然后数位DP即可,ans=cal(r)-cal(l) #include&l ...

  7. BZOJ 1049 数字序列

    Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数 ...

  8. BZOJ 1833 数字计数 数位DP

    题目链接 做的第一道数位DP题,听说是最基础的模板题,但还是花了好长时间才写出来..... 想深入了解下数位DP的请点这里 先设dp数组dp[i][j][k]表示数位是i,以j开头的数k出现的次数 有 ...

  9. BZOJ 1049 数字序列(LIS)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1049 题意:给出一个数列A,要求:(1)修改最少的数字使得数列严格递增:(2)在( ...

随机推荐

  1. 201621123060《JAVA程序设计》第一周学习总结

    1.本周学习总结 1.讲述了JAVA的发展史,关于JDK.JRE.JVM的联系和区别 2.JDK是用JAVA开发工具.做项目的关键.JRE是JAVA的运行环境(JAVA也是JAVA语言开发的).JVM ...

  2. Linux下硬盘分区

    1  fdisk -l查看硬盘及分区信息 我的系统(Archlinux)下的命令效果如下: 由上面的图片可以得知该系统只挂载了1个硬盘,命名为sda,其有2个主分区,sda1和sda2,至于为什么这么 ...

  3. fflush(stdin)与fflush(stdout)

    1.fflush(stdin): 作用:清理标准输入流,把多余的未被保存的数据丢掉.. 如: int main() { int num; char str[10]; cin>>num; c ...

  4. Flask 部署和分发

    到目前为止,启动Flask应用都是通过"app.run()"方法,在开发环境中,这样固然可行,不过到了生产环境上,势必需要采用一个健壮的,功能强大的Web应用服务器来处理各种复杂情 ...

  5. 点击一次按钮,发生多次ajax请求

    项目中遇到了两种情况: 1.点击一次发生两次请求. 原因:submit类型的按钮,默认有提交行为,发生两次提交的原因是在执行完ajax请求后,并没有阻止submit的行为,所以解决方法有两种: a.不 ...

  6. Mysql编译安装详解

    wget http://mirrors.cnnic.cn/apache/httpd/mysql-5.5.20.tar.gz root@Mysql-server ~]# yum install -y c ...

  7. kafka和mqtt的区别是什么?

    两者都是从传统的Pub/Sub消息系统演化出来的,但是进化方向不一样,比较如下: Kafka是为了数据集成的场景,与以往Pub/Sub消息总线不一样,通过分布式架构提供了海量消息处理.高容错的方式存储 ...

  8. angular2 学习笔记 ( translate, i18n 翻译 )

    更新 : 2017-06-17 <h1 i18n="site header|An introduction header for this sample">Hello ...

  9. python flask框架 tempates 模版的使用

    在py文件同级下 建立templates文件夹,再文件夹中编写html文件 1 向模版中传递参数: ''' 1 向模板传送 参数 ''' @app.route('/') def index(): na ...

  10. 浅谈 DML、DDL、DCL的区别

    一.DML DML(data manipulation language)数据操纵语言: 就是我们最经常用到的 SELECT.UPDATE.INSERT.DELETE. 主要用来对数据库的数据进行一些 ...