SAC#1 - 萌数

洛咕

题意:只有满足“存在长度至少为2的回文子串”的数是萌的——也就是说,101是萌的,因为101本身就是一个回文数;110是萌的,因为包含回文子串11;但是102不是萌的,1201也不是萌的.求\([l,r]\)所有整数中有多少个萌数.由于答案可能很大,所以只需要输出答案对\(1e9+7\)的余数.记\(n\)\(r\)在十进制下的位数,\(n<=1000,l<r.\)

分析:考虑求出\([l,r]\)内有多少个数不是萌数,它们一定满足第\(i\)位不等于第\(i-1\)位且第\(i\)位不等于第\(i-2\)位.(因为对于一个回文串\(a\),它在中心对称的地方一定满足\(a[i]=a[i-1]\)或者\(a[i]=a[i-2]\))

因为数字特别大,我们以字符串的形式读入,然后一边取模一边变成\(l,r\),设\([l,r]\)内有\(ans\)个数不是萌数,则最终的答案就是\(r-l+1-ans.\)

然后我们还是先求出\([1,r]\)内不是萌数的个数\(ans2\),再求\([1,l]\)内不是萌数的个数\(ans1\),然后我们判断一下\(l\)是不是萌数,若\(l\)不是萌数则\(--ans1\),则\([l,r]\)内不是萌数的个数为\(ans2-ans1\)个.(这样搞就可以不用判断\(l\)是否为\(0\)了).

一碰到字符串,就必定要注意数组下标等细节问题了.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
const int mod=1e9+7;
string s1,s2;
int n,m,a[1005],b[1005];
ll l,r,dp[1005][10][10];
inline ll dfs(int tot,int pos,int pre2,int pre1,int lead,int limit){
	if(pos>tot)return 1;//找到了一个不是萌数的数
	if(pre2!=-1&&pre1!=-1)//防止数组下标越界
		if(dp[pos][pre1][pre2]!=-1&&!lead&&!limit)return dp[pos][pre1][pre2];
	ll cnt=0;int res=limit?a[tot+1-pos]:9;
	for(int i=0;i<=res;++i){
		if((i==pre1)||(i==pre2))continue;
		if((!i)&&lead)cnt=(cnt+dfs(tot,pos+1,-1,-1,1,limit&&(i==res)))%mod;
		else if(i&&lead)cnt=(cnt+dfs(tot,pos+1,-1,i,0,limit&&(i==res)))%mod;
		else cnt=(cnt+dfs(tot,pos+1,pre1,i,0,limit&&(i==res)))%mod;
	}
	if(pre2!=-1&&pre1!=-1&&!lead&&!limit)dp[pos][pre1][pre2]=cnt;//防止数组下标越界
	return cnt;
}
inline ll solve(){
	for(int i=0;i<n;++i)a[i+1]=s1[n-1-i]-'0';//把下标挪到1-n来
	memset(dp,-1,sizeof(dp));ll ans1=dfs(n,1,-1,-1,1,1);
	for(int i=0;i<m;++i)a[i+1]=s2[m-1-i]-'0';
	memset(dp,-1,sizeof(dp));ll ans2=dfs(m,1,-1,-1,1,1);
	for(int i=0;i<n;++i)a[i+1]=s1[n-1-i]-'0';
	--ans1;//先假设l不是萌数
	for(int i=2;i<=n;i++)
        if(a[i]==a[i-1]||(a[i]==a[i-2]&&(i-2>=1))){
            ans1++;//如果l是萌数,再加回来
            break;
        }
	return ans2-ans1;
}
int main(){
	cin>>s1>>s2;n=s1.size();m=s2.size();
	for(int i=0;i<n;++i)l=(1ll*l*10+s1[i]-'0')%mod;
	for(int i=0;i<m;++i)r=(1ll*r*10+s2[i]-'0')%mod;
	printf("%lld\n",((r-l+1-solve())%mod+mod)%mod);
    return 0;
}

posted on 2019-09-25 21:54  PPXppx  阅读(180)  评论(0编辑  收藏  举报