BZOJ1183 Croatian2008 Umnozak 【数位DP】*
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】*的更多相关文章
- 数位DP复习小结
转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8490222.html 之前学数位dp的时候底子没打扎实 虚的要死 这次正好有时间……刷了刷之前没做的题目 感觉自 ...
- 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP
[BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...
- bzoj1026数位dp
基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- HDU2089 不要62[数位DP]
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 数位DP GYM 100827 E Hill Number
题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...
- 数位dp总结
由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...
- 数位DP入门
HDU 2089 不要62 DESC: 问l, r范围内的没有4和相邻62的数有多少个. #include <stdio.h> #include <string.h> #inc ...
- 数位DP之奥义
恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...
随机推荐
- SQL优化- in和not in
in不会导致索引失效,但最终数据库会将in语句解析为or语句,eg: select * from T_MAIN_PROCESS t where t.audit_status_code in ('05' ...
- intent Filter
intent Filter 一.介绍 如果一个 Intent 请求在一片数据上执行一个动作, Android 如何知道哪个应用程序(和组件)能用来响应这个请求呢? Intent Filter就是 用来 ...
- Oracle Solaris 11.4 GA 版发布,这将是 Solaris 的绝唱
美国当地时间8月28日,Oracle 正式宣布推出 Oracle Solaris 11.4 GA 稳定版,距离上个版本 11.3 的发布已过去近三年.Oracle 的产品管理总监 Scott Lynn ...
- 对于"第一次创业者"应该给什么样的建议
转:其实我创业也不是很成功(目前属于第二次).目前为止,基本保证家里足够温饱和足够温馨,偶尔奢侈,但是我坚持走技术路线,不做土豪(因为做不了). 我创业的口号是:成全别人,累死自己!! 有人问 ...
- poj2187凸包最远点对
暴力过了 #include<map> #include<set> #include<cmath> #include<queue> #include< ...
- Java中子类对象赋值给父类变量
1. 在Java中将一个字类对象赋值给父类变量是合法的,这也是实现多态(即方法的动态分派)的前提条件之一. 2. 在Java中父类赋值同样也适用于数组.可以将一个子类数组赋值给一个父类数组变量.但可能 ...
- LM3S之boot loader学习笔记-1
LM3S之boot loader学习笔记-1 彭会锋 (首先声明,此系列文章编写参考了很多资料,其中一些内容是原版内容的引用和整理,并加入了一些自己的见解,我已经尽量标明引用部分,如有未全部标注部分, ...
- Java读写文化总结
Java读文件 package 天才白痴梦; import java.io.BufferedReader; import java.io.File; import java.io.FileInputS ...
- cocos对象池的使用
enemy.js cc.Class({ extends: cc.Component, properties: { enemySpeed: 0, //设置加速度 }, //初始化当前节点的y坐标 ini ...
- MySQL中文入库问题
中文测试没有问题了,此处bug源于MySQL自身编码的问题,创建数据库默认指定相关编码即可. 创建数据库时,指定utf8编码 CREATE DATABASE mydb DEFAULT CHARACTE ...