1. 程式人生 > >洛谷 3413 萌數

洛谷 3413 萌數

solution 子串 cnblogs tin namespace space urn blog nts

Description

辣雞蒟蒻SOL是一個傻逼,他居然覺得數很萌!

好在在他眼裏,並不是所有數都是萌的。只有滿足“存在長度至少為2的回文子串”的數是萌的——也就是說,101是萌的,因為101本身就是一個回文數;110是萌的,因為包含回文子串11;但是102不是萌的,1201也不是萌的。

現在SOL想知道從l到r的所有整數中有多少個萌數。

由於答案可能很大,所以只需要輸出答案對1000000007(10^9+7)的余數。

Putin

輸入包含僅1行,包含兩個整數:l、r。

Putout

輸出僅1行,包含一個整數,即為答案。

Sample

輸入樣例#1:

1 100
輸出樣例#1:
10
輸入樣例#2:
100 1000
輸出樣例#2:
253

Hints

記n為r在10進制下的位數。

對於10%的數據,n <= 3。

對於30%的數據,n <= 6。

對於60%的數據,n <= 9。

對於全部的數據,n <= 1000,l < r。

Solution

數位dp

dp[i][j][k][l]表示到第i位,上一位為j,上上位為k,目前是(不是)萌數的萌數個數

因為前導0相等不算回文,所以要判前導0

l,r比較大,l-1的話很麻煩,可以把l,r同時帶入或者先算出num(r)-num(l),再判斷l是否是一個萌數

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define nn 1011
#define lo long long
#define mod 1000000007
using namespace std;
lo dp[nn][11][11][2];
char l[nn],r[nn];
int a[nn];
int read()
{
    int ans=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();}
    while(isdigit(ch)) {ans=ans*10+ch-‘0‘;ch=getchar();}
    return ans*f;
}
lo dfs(int w,int pre,int ago,bool lim,bool cute,bool fir)     //位數,上一位,上上位,限制?,萌數?,前導0 
{
	if(w<1)
	  return cute;
	if(!lim&&dp[w][pre][ago][cute]>-1)
	  return dp[w][pre][ago][cute];
	lo ans=0;
	int o=lim? a[w]:9;
	for(int i=0;i<=o;i++)
	  ans=(ans+dfs(w-1,fir&&i==0? -1:i,pre,lim&&i==a[w],cute||i==pre||i==ago,fir&&i==0))%mod;
	if(!lim)
	  dp[w][pre][ago][cute]=ans;
	return ans;
}       
lo solve(char *x)
{
	int w=strlen(x);
	for(int i=0;i<w;i++)
	  a[w-i]=x[i]-‘0‘;
	return dfs(w,-1,-1,1,0,1);
}
int main()
{
	lo ans=0;
	scanf("%s%s",l,r);
	memset(dp,-1,sizeof(dp));
	ans=(solve(r)-solve(l)+mod)%mod;
	int ll=strlen(l);
	for(int i=0;i<ll;i++)
	  if(l[i]==l[i+1]||l[i]==l[i+2])
	  {
	  	ans=(ans+1)%mod;
	  	break;
	  }
	printf("%lld",ans);
}

洛谷 3413 萌數