牛客挑战赛51 C.NIT的数(数位dp)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客挑战赛51 C.NIT的数(数位dp)相关的知识,希望对你有一定的参考价值。

LINK

题意

给你一个正整数 x x x,求第 k k k 小的正整数 y y y 满足 x ≤ y x \\leq y xy y y y 是一个回文数。


写出一个能求出 [ 0 , x ] [0,x] [0,x]有多少回文数的函数就可以使用二分查找来解决问题

那么对于确定的 x x x,设有 r r r位数字

那么 [ 1 , r − 1 ] [1,r-1] [1,r1]位的数字一定都小于 x x x,于是可以直接组合数算出方案

至于那些位数是 r r r的数字,可以用数位 d p dp dp

因为算的是回文数,于是只需要从高位往低位枚举一半就可以直到是否满足条件

如果在 [ r / 2 + 1 , r ] [r/2+1,r] [r/2+1,r]已经分出大小关系就直接返回结果,否则需要知道 [ 1 , r / 2 ] [1,r/2] [1,r/2]的第一个最高位不相等的是比 x x x更大还是更小

定义 f [ i ] [ j ] [ q ] [ w ] f[i][j][q][w] f[i][j][q][w]表示从高位往低位枚举到第 i i i位, [ 1 , r / 2 ] [1,r/2] [1,r/2]中比 x x x大的最高位是第 j j j位,比 x x x小的最高位是第 q q q

当前 [ i , r ] [i,r] [i,r]填数字的限制情况为 w w w

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
#define int long long
int f[22][20][20][2],half,a[20];
int dfs(int len,int pre,int q,int w,int limit)
{
	if( f[len][q][w][limit]!=-1 )	return f[len][q][w][limit];
	if( len<=half )
	{
		if( !limit || w>=q  )	return f[len][q][w][limit] = 1;
		else	return f[len][q][w][limit] = 0;
	}
	int las = limit?a[len]:9, ans = 0;
	for(int i=0;i<=las;i++)
	{
		if( pre==1 && i==0 )	continue;//第一位不能为0 
		int qq = q, ww = w;
		if( i>a[pre] )	qq = pre;
		if( i<a[pre] )	ww = pre;
		ans += dfs( len-1,pre+1,qq,ww,limit&(i==las) );
	}
	return f[len][q][w][limit] = ans;
}
int quick(int x,int n)
{
	int ans = 1;
	for( ; n ; n>>=1,x=x*x )
		if( n&1 )	ans = ans*x;
	return ans;
}
int solve(int x)
{
	if( x==0 )	return 0;
	memset( f,-1,sizeof f );
	a[0] = 0;
	while( x )	a[++a[0]] = x%10, x/=10;
	int ans = 0;
	for(int i=1;i<a[0];i++)
	{
		half = i/2;
		if( i==1 )	ans = 9;
		else
		{
			int temp = 9*quick(10,half-1);
			if( i&1 )	temp = temp*10;
			ans += temp;
		}
	}
	half = a[0]/2;
	return ans+dfs(a[0],1,0,0,1);
}
signed main()
{
	int x,k; cin >> x >> k;
	int sum = solve( x-1 )+k;
	int l = x, r = 1e18, ans = 0;
	while( r>=l )
	{
		int mid = l+r>>1;
		if( solve(mid)<sum )	l = mid+1;
		else	r = mid-1, ans = mid;
	}
	cout << ans;
}

以上是关于牛客挑战赛51 C.NIT的数(数位dp)的主要内容,如果未能解决你的问题,请参考以下文章

[51NOD1230]幸运数(数位DP)

51nod 1043 幸运号码(数位DP)

51Nod 1043 幸运号码 数位DP

51nod1043 幸运号码(数位dp)

51nod 1623 完美消除(数位DP)

牛客每日一题 和与或 数位dp+状态压缩