AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal

https://atcoder.jp/contests/abc194/tasks/abc194_f

太菜了又碰到不会的数位DP题了

这题的关键是我们并不用在dp数组中存下当前已经用了哪些数字

只要令dp[pos][cnt][up][lead]=dp[枚举到哪一位了][有几个不同的数字][是否顶着上界][前面是否有非零位了]

只要其中pos,up,lead,对了,那么对于不同的st有相同的cnt,他们的答案是一样的,所以具体的st并不需要存到dp里面,只需要存位数就行了

#include
using namespace std;
typedef long long ll;

const int maxl=2e5+10;
const int mod=1e9+7;

int n,k;
int a[maxl];
ll dp[maxl][17][2][2];
char s[maxl];

inline ll dfs(int pos,int st,bool up,bool lead)
{
	int cnt=__builtin_popcount(st);
	if(cnt>k) return 0;
	if(pos>n) return cnt==k && lead;
	ll &ret=dp[pos][cnt][up][lead];
	if(ret!=-1)
		return ret;
	ret=0;
	int r=up?a[pos]:15;
	for(int i=0;i<=r;i++)
		ret=(ret+dfs(pos+1,(!i&&!lead)?st:st|(1<='A' && s[i]<='Z')
		a[i]=s[i]-'A'+10;
	else
		a[i]=s[i]-'0';
	memset(dp,-1,sizeof(dp));
	printf("%lld\n",dfs(1,0,1,0));
	return 0;
}

 

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