BZOJ 3679 数位DP,离散化
来源:互联网 发布:linux设置默认启动项 编辑:程序博客网 时间:2024/06/01 09:36
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3679
解法: 比较裸的数位DP,dp[i][j][k]表示前i位,当前位数字为j,乘积为k(k保存的是离散化之后的值),然后按照数位DP的做法去写就可以了。
///BZOJ 3679///数位DP,离散化#include <bits/stdc++.h>using namespace std;typedef long long LL;LL dp[20][10][6000];///dp[i][j][k]前i位,当前位数字为j,乘积为k(k保存的是离散化之后的值)LL l, r;int digit[20];int a[6000];int n, tot, num;map<LL,int>p;///2,3,5,7bool check(int a, int b, int c, int d){ long long ans=1; for(int i=1; i<=a; i++) ans*=2; if(ans>n) return 0; for(int i=1; i<=b; i++) ans*=3; if(ans>n) return 0; for(int i=1; i<=c; i++) ans*=5; if(ans>n) return 0; for(int i=1; i<=d; i++) ans*=7; if(ans>n) return 0; return 1;}int cal(int a, int b, int c, int d){ int ans=1; for(int i=1; i<=a; i++) ans*=2; for(int i=1; i<=b; i++) ans*=3; for(int i=1; i<=c; i++) ans*=5; for(int i=1; i<=d; i++) ans*=7; return ans;}long long f(LL x){ LL ans=0; num=0; while(x){ digit[++num]=x%10; x/=10; } for(int i=1; i<=num/2; i++) swap(digit[i],digit[num-i+1]); for(int i=1; i<num; i++) for(int j=1; j<=9; j++) for(int k=1; k<=tot; k++) ans += dp[num-i][j][k]; LL sum=1; for(int i=1; i<=num; i++){ for(int j=1; j<digit[i]; j++){ for(int k=1; k<=tot; k++){ if(a[k]*sum>n) break; ans+=dp[num-i+1][j][k]; } } sum*=digit[i]; if(sum>n||sum==0) break; } return ans;}int main(){ scanf("%d", &n); for(int i=0; i<=31; i++){ for(int j=0; j<=18; j++){ for(int k=0; k<=13; k++){ for(int l=0; l<=10; l++){ if(check(i,j,k,l)){ a[++tot]=cal(i,j,k,l); } } } } } sort(a+1,a+tot+1); for(int i=1; i<=tot; i++) p[a[i]]=i; scanf("%lld%lld",&l,&r); for(int i=1; i<=9; i++) if(p[i]) dp[1][i][p[i]]=1; for(int i=1; i<=18; i++){ for(int j=1; j<=9; j++){ for(int q=1; q<=tot; q++){ if(dp[i][j][q]){ for(int k=1; k<=9; k++){ if((long long)a[q]*k<=n && p[a[q]*k]) dp[i+1][k][p[a[q]*k]]+=dp[i][j][q]; } } } } } long long ans = f(r)-f(l); printf("%lld\n", ans); return 0;}
DFS版本:
#include <bits/stdc++.h>using namespace std;typedef long long LL;LL dp[20][6000];LL n;int cnt,a[20];map<LL,int> use;LL dfs(int pos,LL chengji,bool lead,bool limit){ if(chengji>n) return 0; if(use[chengji]==0) { use[chengji]=cnt++; } if(pos==-1) { if(chengji>0&&chengji<=n) return 1; return 0; } if(lead==1&&!limit&&dp[pos][use[chengji]]!=-1) return dp[pos][use[chengji]]; int up=limit ? a[pos]:9; LL ret=0; for(int i=0;i<=up;i++) { if(i==0) { if(lead==true) ret+=dfs(pos-1,chengji*i,true,limit&&i==a[pos]); else ret+=dfs(pos-1,0,false,limit&&i==a[pos]); } else { if(lead==true) ret+=dfs(pos-1,chengji*i,true,limit&&i==a[pos]); else ret+=dfs(pos-1,i,true,limit&&i==a[pos]); } } if(!limit&&lead) dp[pos][use[chengji]]=ret; return ret;}LL solve(LL x){ int pos=0; while(x) { a[pos++]=x%10; x/=10; } return dfs(pos-1,0,false,true);}int main(){ memset(dp,-1,sizeof(dp)); LL l,r; use.clear(); cnt=1; scanf("%lld",&n); scanf("%lld%lld",&l,&r); LL ans=solve(r-1)-solve(l-1); printf("%lld\n",ans);return 0;}
0 0
- BZOJ 3679 数位DP,离散化
- codeforces55D(离散化数位dp)
- 数位DP(离散化+技巧)
- Beautiful numbers [数位dp][离散化]
- 【数位DP+离散化】Beautiful numbers CodeForces
- BZOJ 3679 数字之积 - 数位dp
- BZOJ 3679 数字之积 (数位DP)
- [BZOJ]3679: 数字之积 数位DP
- BZOJ-1026 (数位dp)
- BZOJ 3209 数位DP
- BZOJ 1026 数位dp
- BZOJ 1026 数位DP
- BZOJ 1026 (数位dp)
- [数位DP]BZOJ 4513
- CodeForces 55D Beautiful numbers(数位dp&&离散化)
- CodeForces 55DBeautiful numbers 数位dp 离散化
- #51 D. Beautiful numbers (数位dp+离散化)
- CF_55D——Beautiful numbers(离散化数位DP)
- NYOJ 111 分数加减法
- POJ 2352 Stars
- php脚本命令行运行正确,浏览器运行错误
- C/C++堆与栈详悉
- Linux下文件的复制、移动与删除命令
- BZOJ 3679 数位DP,离散化
- web页面国际化---之js翻译插件
- 十四届浙江省赛 E题(数位DP)
- 鼠标拖动面板
- 结构型模式之享元模式(FlyWeight)
- NYOJ 一个简单的数学题
- 正则表达式表匹配所有的两位数字,并且十位为1
- andorid bionic简介
- 点击按钮,缩放图片(img.width、img.style.width、img.offsetWidth)