洛谷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<<"\nnl:"<<nl<<"\n";
for(int i=0;i<lenr;++i)
nr=((nr*10)+r[i]-'0')%mod;
// cout<<"\nnr:"<<nr<<"\n";
printf("%lld",((nr-nl+1-Get())%mod+mod)%mod);
return 0;
}

浙公网安备 33010602011771号