P3413 SAC#1 - 萌数 数位DP 经典题

刚开始看到这题的时候完全没思路。

于是去看题解,看到“ 正难则反 “四个字后,立刻关掉题解(整篇题解只看了这4个字),然后A了这道题。 

相信看到这里你也想试一下!

 

下面说思路,正难则反,考虑1-n种不含回文子串的数。这是个经典问题了:任意连续三个数互不相同即可。

证明:

A:如果连续两个数相同,显然会出现长度为2的回文子串。

B:如果一个数与另一个与他相距2的数相同,显然会出现长度为3的回文子串。

显然任意偶回文子串都是由A拓展而来,任意奇回文子串都是由B拓展而来。

只要保证不存在AB,就能保证不存在回文子串。不存在AB即:任意连续三个数互不相同。

转化到这里就可以直接用数位dp搞了。

dp[i][j][k],处理到第i位,前一位的数为j,前前一位的数为k,后面的数位都未确定的情况下,不含回文子串的数的个数是多少。

然后就是一些细节问题,具体看代码。

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e3+7;
const int mod= 1e9+7;
ll dp[M][11][11];
char s[M]; 
int di[M];
ll dfs(int len,bool limit,int p1,int p2)
{
	if(len==0)return (p1!=10);
	if(!limit && ~dp[len][p1][p2])return dp[len][p1][p2];
	ll cnt=0;
	int up=limit?di[len]:9;
//	cout<>(s+1);
	int n=strlen(s+1);
	
	for(int i=1;i<=n;i++)di[n-i+1]=s[i]-'0';
//	for(int i=1;i<=n;i++)cout<=1;i--)ans*=10,ans+=di[i],ans%=mod;
	
//	cout<

 

你可能感兴趣的:(动态规划----数位DP)