【BZOJ 2713】[Violet 2]愚蠢的副官&&【BZOJ1183】[Croatian2008]Umnozak——【数位DP】

题目链接:

  2713传送门

  1183传送!

题解:

  由于看不懂英文题解(十个单词十一个不认识……),所以只能自己想QAQ。

  其实乱搞就好= =。

  首先我们发现,各位数字乘积要在1e9以下才可能有用,这个很显然。然后发现在1e9以内的满足为各位数字乘积的数只有$5000^+$。我们仿照淘金拉道题的思路。设$f_{(i,j,k)}$表示位数为$i$,第i位数字为$j$,各位数字乘积在$Hash$表里排名为k,转移很好写。然后对于询问的$x$,考虑在$x/Hash_{(k)}$中有多少个满足乘积为$Hash_{(k)}$的即可。

  值得注意的是由于我的码的问题,1应该特判掉。

代码:

 1 #define Troy 
 2  
 3 #include <algorithm>
 4 #include <cstdio>
 5  
 6 using namespace std;
 7  
 8 inline int read(){
 9     int s=0,k=1;char ch=getchar();
10     while(ch<'0'|ch>'9')  ch=='-'?k=-1:0,ch=getchar();
11     while(ch>47&ch<='9')  s=s*10+(ch^48),ch=getchar();
12     return s*k;
13 }
14  
15 typedef long long ll;
16  
17 const int N=6e3;
18  
19 ll Hash[N];int cnt=0;
20 ll f[22][22][N];
21  
22 inline int find(ll x){
23     return upper_bound(Hash+1,Hash+cnt+1,x)-Hash-1;
24 }
25  
26 inline void init(){
27     for(ll x=1;x<=1e9;x*=2)
28         for(ll y=x;y<=1e9;y*=3)
29             for(ll z=y;z<=1e9;z*=5)
30                 for(ll w=z;w<=1e9;w*=7)
31                     Hash[++cnt]=w;  //cnt=5194
32     sort(Hash+1,Hash+cnt+1);
33     for(int i=1;i<=9;i++)
34         f[1][i][i]=1;
35     for(int i=2;i<=18;i++)            
36         for(int k=1;k<=cnt;k++)
37             for(int j=1;j<=9;j++)
38                 if(Hash[k]%j==0){
39                     int x=find(Hash[k]/j);
40                     for(int l=1;l<=9;l++)
41                         f[i][j][k]+=f[i-1][l][x];
42                 }
43 }
44  
45 int p[20],m;
46  
47 inline ll solve(ll x,int pos){
48     if(x==0)    return 0;
49     ll t=1;
50     int tt=pos;
51     m=0;while(x)  p[++m]=x%10,x/=10,t*=p[m];
52     ll ret=0;
53     if(t==Hash[pos])  ret++;
54     for(int i=1;i<m;i++)
55         for(int j=1;j<=9;j++)
56             ret+=f[i][j][pos];
57     for(int i=m;i;i--){
58         for(int j=1;j<p[i];j++)
59             ret+=f[i][j][pos];
60         if(p[i]==0) break;
61         if(Hash[pos]%p[i]!=0)
62             break;
63         pos=find(Hash[pos]/p[i]);
64     }
65     return ret;
66 }
67  
68 inline ll calc(ll x){
69     ll ret=0;
70     for(int i=1;i<=cnt;i++){
71         ret+=solve(x/Hash[i],i);
72     }
73     return ret;
74 }
75  
76 int main(){
77     //freopen("umnozak.in","r",stdin);
78     //freopen("umnozak.out","w",stdout);
79     init();
80     ll L,R;
81     scanf("%lld%lld",&L,&R);
82     printf("%lld\n",calc(R)-calc(L-1));
83 }

 

posted @ 2017-10-24 11:51  Troywar  阅读(427)  评论(0编辑  收藏  举报