码迷,mamicode.com
首页 > 其他好文 > 详细

数位DP 2

时间:2017-09-03 13:20:30      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:sort   opened   pos   void   cto   oid   typedef   tor   size   

1.3679 数字之积

很套路的数位DP

关键在于预处理出所有可能的乘积,爆搜是9^18好像,反正几年跑出来(SXY大佬帮我算的这个)

根据唯一分解定理,因为所有数都是1~9,所以只要枚举2^a*3^b*5^c*7^d就可以预处理出来了。

技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
const int maxn=1e9;
LL tp,n,a[6000],dp[20][6000],sz,l,r,ansl,ansr;
int lim[20],cnt;
void pre(){
    for(int i=0;i<=30;i++)
      for(int j=0;j<=19;j++)
        for(int k=0;k<=13;k++)
          for(int l=0;l<=11;l++){
             LL res=pow(2,i)*pow(3,j)*pow(5,k)*pow(7,l);
             if(res>0&&res<=n) a[++sz]=res;
        }
    sort(a+1,a+sz+1);
} 
LL dfs(int pos,int sum,int limit,int flag){
    if(!pos) return 1;
    if(!limit&&~dp[pos][sum]) return dp[pos][sum];
    int up=limit?lim[pos]:9; 
    LL res=0;
    for(int i=(!flag||(flag&&pos==1));i<=up;i++){
        LL realsum=a[sum];
        if(flag) realsum=1;
        if(realsum*i>n) break;
        if(realsum*i<=n){
        int now=lower_bound(a,a+sz+1,realsum*i)-a;
        res+=dfs(pos-1,now,limit&&i==lim[pos],flag&&i==0);
        }
    }
    if(!limit) dp[pos][sum]=res;
    return res;
}
void cal(LL x,LL &ans){
    if(!x) {return;}
    memset(dp,-1,sizeof(dp));
    cnt=0; tp=x;
    while(tp) {lim[++cnt]=tp%10; tp/=10;}
    ans+=dfs(cnt,1,1,1);
}
int main()
{
    scanf("%lld%lld%lld",&n,&l,&r);
    pre(); 
    cal(l-1,ansl);
    cal(r-1,ansr);
    printf("%lld\n",ansr-ansl);
    return 0;
}
3679 数字之积

 

数位DP 2

标签:sort   opened   pos   void   cto   oid   typedef   tor   size   

原文地址:http://www.cnblogs.com/Achenchen/p/7469318.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!