• 洛谷 3413 萌数


    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是否是一个萌数

    感谢xy指正bug,那个pre,ago可能为-1,要加一个1

    #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+1][ago+1][cute]>-1)
    	  return dp[w][pre+1][ago+1][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+1][ago+1][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);
    }
  • 相关阅读:
    mysql密码忘记如何恢复(windows/liunx版本:mysql8.0.27)
    Visual Studio Code如何校验yaml格式文件
    python测试小工具
    Lunx vimgo 开发环境搭建
    小白学正则表达式之 regexp
    kubernetes scc 故障排查小记
    Go image registry
    OpenShift image registry 概述
    Go 疑难杂症汇总
    小白学标准库之 http
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7622791.html
Copyright © 2020-2023  润新知