BZOJ1183 Croatian2008 Umnozak


Description

定义一个数的digit-product是它的各个位上的数字的乘积,定义一个数的self-product是它本身乘以它的digit-pr
oduct。编程求self-product在a和b之间的数的个数。

Input

两个整数a,b(1 ≤ a ≤ b < 10^18)。

Output

一个整数,self-product在a和b之间的数的个数。

Sample Input

145 192

Sample Output

4


数位DP,我么发现digit-product包含的质因子最多只有2,3,5,7,digit-product严格小于原数,所以digit-product不会超过1e9,所以我们可以对这个数进行枚举,只有很少的可能取值

然后我们确定了digit-product之后就可以确定原数的上下界,然后利用digit-product中,2,3,5,7的质因子个数来进行DP,注意一下边界问题什么的

。。。

反正我照标程调的


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL l,r,ans=0;
LL dp[18][30][19][13][11];
LL f[4]={2,3,5,7};
LL k[4]={0,0,0,0};
LL cnt[10][4]={
{0,0,0,0},
{0,0,0,0},
{1,0,0,0},
{0,1,0,0},
{2,0,0,0},
{0,0,1,0},
{1,1,0,0},
{0,0,0,1},
{3,0,0,0},
{0,2,0,0}
};
LL dfs(LL len,LL a,LL pot,LL l_line,LL r_line){
LL b=a+pot-1;
if(a>r_line||b<l_line)return 0;
if(len==18)return (!k[0])&&(!k[1])&&(!k[2])&&(!k[3]);
bool mem=(a>=l_line&&b<=r_line);
if(mem&&dp[len][k[0]][k[1]][k[2]][k[3]]>=0)
return dp[len][k[0]][k[1]][k[2]][k[3]];
pot/=10;
LL res=0;
for(LL i=(a!=0);i<=9;++i){
LL t=1;
for(LL j=0;j<4;j++)if(cnt[i][j]>k[j])t=0;
if(!t)continue;
for(LL j=0;j<4;j++)k[j]-=cnt[i][j];
res+=dfs(len+1,a+i*pot,pot,l_line,r_line);
for(LL j=0;j<4;j++)k[j]+=cnt[i][j];
}
if(mem)dp[len][k[0]][k[1]][k[2]][k[3]]=res;
return res;
}
LL getL(LL a,LL b){return (a+b-1)/b;}
LL getR(LL a,LL b){return a/b;}
void getans(LL up,LL prod,LL tip){
if(prod>(LL)1e9||prod*prod>up)return;
if(tip==4){
ans+=dfs(0,0,(LL)1e18,getL(l,prod),getR(r,prod));
return;
}
getans(up,prod,tip+1);
++k[tip];
getans(up,prod*f[tip],tip);
--k[tip];
}
int main(){
cin>>l>>r;
memset(dp,-1,sizeof(dp));
getans(r,1,0);
printf("%lld\n",ans);
return 0;
}

标程:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib> using namespace std; typedef long long llint; llint memo[18][30][19][13][11]; int f[4] = { 2, 3, 5, 7 };
int k[4] = { 0, 0, 0, 0 };
int code[10][4] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 2, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 1 },
{ 3, 0, 0, 0 },
{ 0, 2, 0, 0 }
}; llint rec( int digits, llint a, llint pot, llint lo, llint hi ) {
llint b = a + pot-1;
if( a > hi || b < lo ) return 0;
if( digits == 18 ) return !k[0] && !k[1] && !k[2] && !k[3]; int memoize = 0;
if( a >= lo && b <= hi ) memoize = 1; if( memoize && memo[digits][k[0]][k[1]][k[2]][k[3]] >= 0 )
return memo[digits][k[0]][k[1]][k[2]][k[3]]; pot /= 10; llint ret = 0; for( int digit = (a!=0); digit <= 9; ++digit ) { int ok = 1;
for( int i = 0; i < 4; ++i ) ok &= code[digit][i] <= k[i];
if( !ok ) continue; for( int i = 0; i < 4; ++i ) k[i] -= code[digit][i];
ret += rec( digits+1, a + digit*pot, pot, lo, hi );
for( int i = 0; i < 4; ++i ) k[i] += code[digit][i];
} if( memoize ) memo[digits][k[0]][k[1]][k[2]][k[3]] = ret; return ret;
} llint lo, hi;
llint rjesenje; llint ceil( llint a, llint b ) { return (a+b-1)/b; }
llint floor( llint a, llint b ) { return a/b; } void gen( llint limit, llint product, int factor ) {
if( product > 1000000000 || product*product > limit ) return;
if( factor == 4 ) {
rjesenje += rec( 0, 0, 1000000000000000000LL, ceil(lo,product), floor(hi,product) );
return;
} gen( limit, product, factor + 1 );
++k[factor];
gen( limit, product*f[factor], factor );
--k[factor];
} int main( void ) {
scanf( "%lld%lld", &lo, &hi ); memset( memo, -1, sizeof memo ); gen( hi, 1, 0 ); printf( "%lld\n", rjesenje ); return 0;
}

BZOJ1183 Croatian2008 Umnozak 【数位DP】*的更多相关文章

  1. 数位DP复习小结

    转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8490222.html 之前学数位dp的时候底子没打扎实 虚的要死 这次正好有时间……刷了刷之前没做的题目 感觉自 ...

  2. 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP

    [BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...

  3. bzoj1026数位dp

    基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...

  4. uva12063数位dp

    辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...

  5. HDU2089 不要62[数位DP]

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  6. 数位DP GYM 100827 E Hill Number

    题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...

  7. 数位dp总结

    由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...

  8. 数位DP入门

    HDU 2089 不要62 DESC: 问l, r范围内的没有4和相邻62的数有多少个. #include <stdio.h> #include <string.h> #inc ...

  9. 数位DP之奥义

    恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...

随机推荐

  1. Java环境搭建指南

    1.1 配置Java环境 1.  下载并安装Jdk1.7或Jdk1.8 http://www.oracle.com/technetwork/java/javase/downloads/index.ht ...

  2. CDN专业一站式解决方案

    调度,弱网加速,动态防御,无限节点(重)新技术

  3. Python基础笔记系列七:字符串定义和访问

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 字符串定义和访问 1.字符串基础 a.字符串可以用单引号.双引号.三引号( ...

  4. Partition List,拆分链表

    问题描述: Given a linked list and a value x, partition it such that all nodes less than x come before no ...

  5. linux pgrep命令的使用

    pgrep 是通过程序的名字来查询进程的工具,一般是用来判断程序是否正在运行. 常用参数 -l 列出程序名和进程ID -o 进程起始的ID -n 进程终止的ID $ ps -ef | grep mys ...

  6. git 提交作业流程

    git 提交作业流程,主要分为4个步骤 # 拉取远程git最新版本到本地,每次都可以先执行这条命令,因为会有其他同学更新仓库 git pull # add需要上传的文件,那个文件修改或者新增的,就ad ...

  7. 解决无法启动mysql服务错误1069

    之前在服务器上修改了my.ini文件 mysql就一直无法启动 后来把my.ini改回原来的,还是无法启动并报1069错误 在网上查了一下,基本上都是说修改mysql密码,再重新启动,试了一下没作用, ...

  8. ZOJ 2599 Graduated Lexicographical Ordering ★(数位DP)

    题意 定义两个数的比较方法,各位数字之和大的数大,如果数字和相等则按字典序比较两个数的大小.输入n,k,求:1.数字k的排名:2.排名为k的数. 思路 算是一类经典的统计问题的拓展吧~ 先来看第一问. ...

  9. Ansible 开发调试 之【pycharm远程调试】

    介绍 PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成.单元测试.版本 ...

  10. Spring入门3.AOP编程

    Spring入门3.AOP编程 代码下载: 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa 前言: 前面学习的知识是Spring在Java项目中的IoC或DJ,这 ...