HDU - 6156

题目链接:HDU - 6156


数位dp即可,每次转移的时候记录每个字符串的长度,以及当前选了的位数。

如果选了未超过一半,那么都可以选,否则只能选之前选的对称位的值。

注意处理前导零。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=90;
int dp[N][N][N],a[N],ts,b[N]; long long res;
int dfs(int pos,int len,int k,int zero,int lim){
	if(!pos)	return 1;
	if(!zero&&!lim&&dp[pos][len][k]!=-1)	return dp[pos][len][k];
	int up=lim?a[pos]:k-1,res=0;
	for(int i=0;i<=up;i++){
		b[pos]=i;
		if(zero&&!i) res+=dfs(pos-1,len-1,k,1,lim&&i==up);
		else if(pos>len/2)	res+=dfs(pos-1,len,k,0,lim&&i==up);
		else if(i==b[len-pos+1]) res+=dfs(pos-1,len,k,0,lim&&i==up);
	}
	if(!lim&&!zero) dp[pos][len][k]=res;
	return res;
}
inline int calc(int x,int k){
	int pos=0;
	while(x)	a[++pos]=x%k,x/=k;
	return dfs(pos,pos,k,1,1);
}
inline void solve(){
	int l,r,L,R; res=0;
	scanf("%lld %lld %lld %lld",&L,&R,&l,&r);
	for(int i=l;i<=r;i++){
		int tmp=calc(R,i)-calc(L-1,i);
		res+=tmp*i+(R-L+1-tmp);
	}
	printf("Case #%lld: %lld\n",++ts,res);
}
signed main(){
	memset(dp,-1,sizeof dp);
	int T; cin>>T; while(T--) solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107771933
hdu
今日推荐