数位DP。
比较蛋疼的是,设a[i]表示第i位上数字,比方说a[1]<a[2]>a[3],且a[1]==a[3]时,这两位上的数可以放在一起搞掉。
所以就在正常的f数组里多开一维,表示后面那些位组成的不增的单调栈中,包含的数字集合。
f[i][j][k][a]表示i位,首位为j,单调栈数字集合为k,最小消除数为a的数字个数。
从已知往外推好像好写一点。。
枚举f[i1][j1][k1][a1],再枚举下一个首位j
若j<j1: f[i1+1][j][ (k1%2^(j+1))|2^j ][ a1+(2^j&k1?0:1) ]+=f[i1][j1][k1][a1];
若j==j1:f[i1+1][j][k1][a1]+=f[i1][j1][k1][a1];
若j>j1: f[i1+1][j][k1+2^j][a1+1]+=f[i1][j1][k1][a1];
统计答案时,就在记录一下已确定高位的不减单调栈就行了。。。
很(jiao)显(wan)而(cai)易(fa)见(xian)的是...j那维是没用的,因为j肯定是k的最大位...所以每个k都对应着唯一的j
反正都交了。。就懒得改了>_<
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 ll f[19][10][1025][19]; 7 int two[19],one[19]; 8 int i,j,k,n,m,aa; 9 int s[23],st[23],top; 10 ll L,R; 11 12 inline void prerun(){ 13 register int k1,a1,j;int i1,j1,i;ll now; 14 for(i=one[0]=two[0]=1;i<10;i++)two[i]=two[i-1]<<1,one[i]=one[i-1]<<1|1; 15 for(i=0;i<10;i++)f[1][i][two[i]][i!=0]=1; 16 for(i1=1;i1<18;i1++) 17 for(j1=0;j1<10;j1++)for(k1=two[j1];k1<=one[j1];k1++)for(a1=0;a1<=i1&&a1<=aa;a1++) 18 if(f[i1][j1][k1][a1]){ 19 now=f[i1][j1][k1][a1]; 20 f[i1+1][0][1][a1]+=now; 21 for(j=1;j<j1;j++) 22 f[i1+1][j][(k1&one[j])|two[j]][a1+!(k1&two[j])]+=now; 23 if(j1!=0)f[i1+1][j1][k1][a1]+=now; 24 for(j=j1+1;j<10;j++) 25 f[i1+1][j][k1|two[j]][a1+1]+=now; 26 } 27 } 28 inline int calc(int k){ 29 register int sm=0,i; 30 for(i=1;i<=top;i++)if((st[i]!=st[i-1]||i==1)&&st[i]>0) 31 if(!(two[st[i]]&k))sm++; 32 return sm; 33 } 34 inline ll get(ll x){ 35 if(!x)return 0; 36 ll tmp=x,ans=0;int len=0;register int i,j,k; 37 while(tmp)s[++len]=tmp%10,tmp/=10; 38 for(i=1;i<len;i++)for(j=1;j<=9;j++)for(k=two[j];k<=one[j];k++) 39 ans+=f[i][j][k][aa]; 40 for(j=1;j<s[len];j++)for(k=two[j];k<=one[j];k++) 41 ans+=f[len][j][k][aa]; 42 int pre=0,tmpa;st[top=1]=s[len]; 43 for(i=len-1;i;i--){ 44 if(pre>aa)break; 45 for(j=0;j<s[i];j++) 46 for(k=two[j];k<=one[j];k++) 47 if((tmpa=aa-pre-calc(k))>=0) 48 ans+=f[i][j][k][tmpa]; 49 while(top&&st[top]>s[i])pre+=(st[top]!=st[top-1]||top==1),top--; 50 st[++top]=s[i]; 51 } 52 if(pre+calc(0)==aa)ans++; 53 return ans; 54 } 55 int main(){ 56 scanf("%lld%lld%d",&L,&R,&aa); 57 prerun(); 58 printf("%lld ",get(R)-get(L-1)); 59 return 0; 60 }