[BZOJ3679][数位DP]数字之积

学一发数位DP
如果直接记录乘积的话有 109 的情况,但是因为每一位只有1~9,所以最后乘积只有2 3 5 7的质因数,那么把在第i为放0~9转化成放入多少个2 3 5 7
f(i,c2,c3,c5,c7,j) 表示转移到从高到低的第i位,因数2的个数为c2,3的个数为c3,5的个数为c5,7的个数为c7,j表示到i位的数字是否等于R的,然后转移一下 就好了…

#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

int n;
int w[20],wt;
int add[10][5];
ll f[2][32][21][14][13][2];
ll p2[32],p3[21],p5[14],p7[13];
ll L,R;

inline ll solve(ll lt,int n){
  memset(f,0,sizeof(f));
  int k=0; wt=0; ll x=lt,ret=0;
  while(x) w[++wt]=x%10,x/=10;
  for(int i=1;i<=w[wt];i++)
    if(i>n) break; else
      if(i==w[wt]) f[0][add[i][1]][add[i][2]][add[i][3]][add[i][4]][1]=1;
      else f[0][add[i][1]][add[i][2]][add[i][3]][add[i][4]][0]=1;
  for(int j=wt-1;j;j--){
    k^=1;
    for(int i=1;i<=9;i++)
      if(i<=n) f[k][add[i][1]][add[i][2]][add[i][3]][add[i][4]][0]=1;
    for(int i1=0;i1<=30;i1++)
      if(p2[i1]<=n)
    for(int i2=0;i2<=19;i2++)
      if(p3[i2]*p2[i1]<=n)
        for(int i3=0;i3<=13;i3++)
          if(p5[i3]*p3[i2]*p2[i1]<=n)
        for(int i4=0;i4<=11;i4++)
          if(p7[i4]*p2[i1]*p3[i2]*p5[i3]<=n){
            ll now=p2[i1]*p3[i2]*p5[i3]*p7[i4];
            for(int i=1;i<=9;i++){
              if(i*now>n) break;
              f[k][i1+add[i][1]][i2+add[i][2]][i3+add[i][3]][i4+add[i][4]][0]+=f[k^1][i1][i2][i3][i4][0];
              if(i>w[j]) continue;
              if(i1]][i2+add[i][2]][i3+add[i][3]][i4+add[i][4]][0]+=f[k^1][i1][i2][i3][i4][1];
              else f[k][i1+add[i][1]][i2+add[i][2]][i3+add[i][3]][i4+add[i][4]][1]+=f[k^1][i1][i2][i3][i4][1];
            }
          }
    for(int i1=0;i1<=30;i1++)
      for(int i2=0;i2<=19;i2++)
    for(int i3=0;i3<=13;i3++)
      for(int i4=0;i4<=11;i4++)
        f[k^1][i1][i2][i3][i4][0]=f[k^1][i1][i2][i3][i4][1]=0;
  }
  for(int i1=0;i1<=30;i1++)
    for(int i2=0;i2<=19;i2++)
      for(int i3=0;i3<=13;i3++)
    for(int i4=0;i4<=11;i4++)
      ret+=f[k][i1][i2][i3][i4][0],f[k][i1][i2][i3][i4][0]=f[k][i1][i2][i3][i4][1]=0;
  return ret;
}

int main(){
  cin>>n>>L>>R;
  p2[0]=p3[0]=p5[0]=p7[0]=1;
  for(int i=1;i<=30;i++) p2[i]=p2[i-1]*2;
  for(int i=1;i<=19;i++) p3[i]=p3[i-1]*3;
  for(int i=1;i<=13;i++) p5[i]=p5[i-1]*5;
  for(int i=1;i<=11;i++) p7[i]=p7[i-1]*7;
  add[2][1]=1; add[3][2]=1; add[4][1]=2; add[5][3]=1;
  add[6][1]=1; add[6][2]=1; add[7][4]=1; add[8][1]=3;
  add[9][2]=2;
  cout<return 0;
}

你可能感兴趣的:(DP,数位DP)