[数位DP] BZOJ 2713 [Violet 2]愚蠢的副官 & BZOJ 1183 [Croatian2008]Umnozak

来源:互联网 发布:网络传销模式 编辑:程序博客网 时间:2024/05/21 10:52

官方题解

The first observation we can make is that, for all positive integers x, the digit-product p(x) is always less than or equal to x. From xp(x)B1018 we can deduce that p(x)B109
Because p(x) is a product of digits, its prime factors can only be 2, 3, 5 and 7. The number of different integers with only 2, 3, 5 and 7 in their prime factorization that are less than or equal to 109 is quite small (exactly 5194).

然后就很显然了
枚举出p(x) 然后找小于等于n/p(x)的满足条件的x
简单的数位DP 我不顾及复杂度地乱写一通竟然过了
为什么std跑的那么快 嘤嘤嘤

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<map>using namespace std;typedef long long ll;const int fact[]={2,3,5,7};  const int C[11][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}  };int f[25][45][35][25][25];inline ll count(ll n,int a,int b,int c,int d){  if (!n) return 0;  int w[20]={0},m=0; n++;  for (ll t=n;t;w[++m]=t%10,t/=10); reverse(w+1,w+m+1);  for (int t=1;t<=m;t++)    for (int i=0;i<=a;i++)      for (int j=0;j<=b;j++)    for (int k=0;k<=c;k++)      for (int l=0;l<=d;l++) f[t][i][j][k][l]=0;  int p[4]={0}; int flag=0;  for (int t=1;t<=m;t++){    for (int r=1;r<=9;r++)      for (int i=0;i+C[r][0]<=a;i++)    for (int j=0;j+C[r][1]<=b;j++)      for (int k=0;k+C[r][2]<=c;k++)        for (int l=0;l+C[r][3]<=d;l++)          f[t][i+C[r][0]][j+C[r][1]][k+C[r][2]][l+C[r][3]]+=f[t-1][i][j][k][l];    if (!flag)      for (int r=1;r<w[t];r++)    f[t][p[0]+C[r][0]][p[1]+C[r][1]][p[2]+C[r][2]][p[3]+C[r][3]]++;    if (t!=1){      for (int r=1;r<=9;r++)    f[t][C[r][0]][C[r][1]][C[r][2]][C[r][3]]++;    }    if (!w[t])      flag=1;    else      for (int i=0;i<4;i++)    p[i]+=C[w[t]][i];  }  return f[m][a][b][c][d];}inline ll Solve(ll n){  if (!n) return 0;  ll a,b,c,d; int i,j,k,l; ll B=sqrt(n);  ll ret=0;  for (i=0,a=1;a<=B;i++,a*=fact[0])    for (j=0,b=a;b<=B;j++,b*=fact[1])      for (k=0,c=b;c<=B;k++,c*=fact[2])    for (l=0,d=c;d<=B;l++,d*=fact[3])      ret+=count(n/d,i,j,k,l);  return ret;}int main(){  ll L,R;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  scanf("%lld%lld",&L,&R);  printf("%lld\n",Solve(R)-Solve(L-1));  return 0;}
0 0
原创粉丝点击