SAC#1 - 萌数

P3413 SAC#1 - 萌数

解题思路:

我们反着来考虑这道题:如何判断一个数不含回文串。

思考一下,会发现:当一个数的任意一位都不和前两位的数字相同时,这个数就不含回文串

\(f[pos][pre][gpre]\) 表示在 \(pos\) 位时前一位是 \(epre\) 前两位是 \(gpre\) 的非回文串数.

利用字符串读入,转移时注意前导零不要识别成合法的前缀,即可解决。

// P3413 SAC#1 - 萌数
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7,N=1005;
string l,r;
int len[N];
int f[N][10][10];
int dfs(int pos,int pre,int gpre,bool lim,bool zero){
	if(pos==0) return 1;
	if(f[pos][pre][gpre]!=-1&&!lim&&!zero&&pre!=-1&&gpre!=-1) return f[pos][pre][gpre];
	int up=lim?len[pos]:9;
	int ans=0;
	for(int i=0;i<=up;i++){
		if(i!=pre&&i!=gpre&&!zero)
			ans=(ans+dfs(pos-1,i,pre,lim&&i==len[pos],0))%mod;
		else if(zero)
			ans=(ans+dfs(pos-1,(i==0&&zero)?-1:i,-1,lim&&i==len[pos],i==0&&zero))%mod;
	}
	if(!lim&&!zero&&pre!=-1&&gpre!=-1) return f[pos][pre][gpre]=ans;
	return ans;
}
int slove(){
	int s=l.length();
	for(int i=0;i<s;i++) len[s-i]=l[i]-'0';
	int ans1=dfs(s,-1,-1,1,1);
	s=r.length();
	for(int i=0;i<s;i++) len[s-i]=r[i]-'0';
	int ans2=dfs(s,-1,-1,1,1);
	ans1--;
	s=l.length();
	for(int i=2;i<=s;i++)
		if(l[i]==l[i-1]||(l[i]==l[i-2]&&(i-2>=1))){
			ans1++; break;
		}
	return (ans2-ans1)%mod;
}
signed main(){
	cin>>l>>r;
	memset(f,-1,sizeof f);
	int L=0,R=0;
	int s1=l.length(),s2=r.length();
	for(int i=0;i<s1;i++) L=(L*10%mod+(l[i]^48))%mod;
	for(int i=0;i<s2;i++) R=(R*10%mod+(r[i]^48))%mod;
	printf("%lld\n",((R-L-slove()+1)%mod+mod)%mod);
    system("pause");
	return 0;
} 
posted @ 2021-09-18 19:41  Evitagen  阅读(39)  评论(0编辑  收藏  举报