BZOJ3679 : 数字之积

f[i][p2][p3][p5][p7][j][k]表示前i位,2,3,5,7的次数,前i位是否等于x,是否有数字的方案数

然后数位DP即可,ans=cal(r)-cal(l)

 

#include<cstdio>
typedef long long ll;
int n,a[20],len,i,j,m2,m3,m5,m7,t,p2,p3,p5,p7,c2[10],c3[10],c5[10],c7[10],pow2[30],pow3[20],pow5[14],pow7[12];
ll l,r,tmp,f[20][30][20][14][12][2][2];
ll cal(ll x){
  for(len=0,tmp=x;tmp;a[++len]=tmp%10,tmp/=10);
  for(i=1,j=len;i<=len&&i<j;i++,j--)t=a[i],a[i]=a[j],a[j]=t;
  for(i=1;i<=len;i++)for(p2=0;p2<=m2;p2++)for(p3=0;p3<=m3;p3++)for(p5=0;p5<=m5;p5++)for(p7=0;p7<=m7;p7++)f[i][p2][p3][p5][p7][0][0]=f[i][p2][p3][p5][p7][0][1]=f[i][p2][p3][p5][p7][1][1]=0;
  for(i=0;i<=a[1];i++)f[1][c2[i]][c3[i]][c5[i]][c7[i]][i==a[1]][i>0]=1;
  for(i=1;i<len;i++)for(p2=0;p2<=m2;p2++)for(p3=0;p3<=m3;p3++)for(p5=0;p5<=m5;p5++)for(p7=0;p7<=m7;p7++)if(pow2[p2]*pow3[p3]*pow5[p5]*pow7[p7]<=n){
    if(f[i][p2][p3][p5][p7][0][0])for(j=0;j<=9;j++)f[i+1][p2+c2[j]][p3+c3[j]][p5+c5[j]][p7+c7[j]][0][j>0]+=f[i][p2][p3][p5][p7][0][0];
    if(f[i][p2][p3][p5][p7][0][1])for(j=1;j<=9;j++)f[i+1][p2+c2[j]][p3+c3[j]][p5+c5[j]][p7+c7[j]][0][1]+=f[i][p2][p3][p5][p7][0][1];
    if(f[i][p2][p3][p5][p7][1][1])for(j=1;j<=a[i+1];j++)f[i+1][p2+c2[j]][p3+c3[j]][p5+c5[j]][p7+c7[j]][j==a[i+1]][1]+=f[i][p2][p3][p5][p7][1][1];
  }
  for(p2=0;p2<=m2;p2++)for(p3=0;p3<=m3;p3++)for(p5=0;p5<=m5;p5++)for(p7=0;p7<=m7;p7++)if(pow2[p2]*pow3[p3]*pow5[p5]*pow7[p7]<=n)tmp+=f[len][p2][p3][p5][p7][0][1];
  return tmp;
}
int main(){
  c2[2]=1;c3[3]=1;c2[4]=2;c5[5]=1;c2[6]=1;c3[6]=1;c7[7]=1;c2[8]=3;c3[9]=2;
  scanf("%d%lld%lld",&n,&l,&r);
  for(t=n;t>1;t/=2,m2++);
  for(t=n;t>1;t/=3,m3++);
  for(t=n;t>1;t/=5,m5++);
  for(t=n;t>1;t/=7,m7++);
  for(i=pow2[0]=1;i<=m2;i++)pow2[i]=pow2[i-1]*2;
  for(i=pow3[0]=1;i<=m3;i++)pow3[i]=pow3[i-1]*3;
  for(i=pow5[0]=1;i<=m5;i++)pow5[i]=pow5[i-1]*5;
  for(i=pow7[0]=1;i<=m7;i++)pow7[i]=pow7[i-1]*7;
  printf("%lld",cal(r)-cal(l));
  return 0;
}

  

 

posted @ 2014-09-10 16:26  Claris  阅读(422)  评论(0编辑  收藏  举报