Problem
http://acm.hdu.edu.cn/showproblem.php?pid=4352
Solution
數位DP+LIS+狀壓
解題前奏:nlogn LIS
具體:記錄前len位的LIS情況,可以預處理sta+i後的newsta,然後DFS,DP寫超時(10000組)
CODE
/*
* @key word:digit DP
* @tesed on:HDU4352 62ms
* @Author: lhq
* @Date: 2017-08-15 12:30:13
* @Last Modified by: lhq
* @Last Modified time: 2017-08-15 12:30:36
*/
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
int change[1<<10][10],one[1<<10],a[20],K;
ll dp[20][1<<10][11];
ll dfs(int len,int sta,bool limit)
{
if (len==0) return one[sta]==K?1:0;
if (!limit && dp[len][sta][K]!=-1) return dp[len][sta][K];
int up=limit?a[len]:9;
ll ans=0;
for (int i=0;i<=up;i++)
ans+=dfs(len-1,change[sta][i],limit && i==up);
if (!limit) dp[len][sta][K]=ans;
return ans;
}
ll solve(ll x)
{
int len=0;
while (x)
{
a[++len]=x%10;
x/=10;
}
return dfs(len,0,true);
}
void prepare()
{
memset(dp,-1,sizeof(dp));
for (int i=0;i<1<<10;i++)
for (int j=0;j<=9;j++)
{
if (i==0 && j==0) continue;
int p=i;
for (int k=j;k<=9;k++)
if (p & (1<<k)) {p^=1<<k; break;}
change[i][j]=p^(1<<j);
}
for (int i=0;i<1<<10;i++)
for (int j=0;j<=9;j++)
if (i & 1<<j) one[i]++;
}
int main()
{
prepare();
int T;
cin>>T;
for (int i=1;i<=T;i++)
{
ll l,r;
scanf("%lld%lld%d",&l,&r,&K);
printf("Case #%d: %lld\n",i,solve(r)-solve(l-1));
}
return 0;
}