洛谷P3413 SAC#1

洛谷题目链接

真毒瘤。。

这个题目真的耗了我半小时!其实现在想起来还好,思路应该不难想,这里提供一种思路,一开始看这题想着不好判断回文,既然回文不好判断,那就判断不回文呗,正难则反嘛~~~我们要知道,对于一个不是回文串的串,每个字符与前面一个字符和前面第二个字符不相同,因此我们记录两个值$last1,last2$表示上一位的值以及上两位的值,剩下的就是数位$dp$啦~~~

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define int long long
#define ll long long
#define N 1010
#define mod 1000000007
using namespace std;
int val[N];
char l[N],r[N];
int f[N][21][21];
ll lenl,lenr;
ll Dfs(int pos,int last2,int last1,bool limit,bool lead)
{
	if(!pos)
		return 1;
	if(!limit&&!lead&&f[pos][last2][last1]!=-1)
		return f[pos][last2][last1]%mod;
	int maxn=limit?val[pos]:9;
	ll ans=0;
	for(int i=0;i<=maxn;++i)
	{
		if(lead&&!i)
			ans=(ans+Dfs(pos-1,-1,-1,limit&&(i==maxn),1)%mod)%mod;
		else
			if(i!=last1&&i!=last2)
				ans=(ans+Dfs(pos-1,last1,i,limit&&(i==maxn),0)%mod)%mod;
	}
	if(!limit&&!lead)
		f[pos][last2][last1]=ans%mod;
	return ans%mod;
}
ll Get()
{
	for(int i=0;i<lenl;++i)
		val[lenl-i]=l[i]-'0';
	ll numl=Dfs(lenl,-1,-1,1,1)%mod;
	--numl;
	for(int i=0;i<lenr;++i)
		val[lenr-i]=r[i]-'0';
	ll numr=Dfs(lenr,-1,-1,1,1)%mod;
	for(int i=2;i<lenl;++i)
		if(l[i]==l[i-1]||l[i]==l[i-2])
		{
			++numl;
			break;	
		}
	return (numr-numl)%mod;
}
signed main()
{
	cin>>l>>r;
	lenl=strlen(l),lenr=strlen(r);
	memset(f,-1,sizeof(f));
	ll nl=0,nr=0;
	for(int i=0;i<lenl;++i)
		nl=((nl*10)+l[i]-'0')%mod;
//	cout<<"
nl:"<<nl<<"
";
	for(int i=0;i<lenr;++i)
		nr=((nr*10)+r[i]-'0')%mod;
//	cout<<"
nr:"<<nr<<"
";
	printf("%lld",((nr-nl+1-Get())%mod+mod)%mod);
	return 0;
}

  

原文地址:https://www.cnblogs.com/yexinqwq/p/10235087.html