[SAC#1] 萌数 解题记录

SAC#1 - 萌数 解题记录


题意简述

求出 [ l , r ] [l,r] [l,r] 区间内的包含长度至少为 2 2 2 的数的个数,答案对 1 0 9 + 7 10^9+7 109+7 取模。


题目分析

一个长度 ≥ 2 \geq 2 2 的回文串一定在它的正中间有形如 a a ‾ \overline{aa} aa a b a ‾ \overline{aba} aba 的字串,其中 a a ‾ \overline{aa} aa 即长度为偶数, a b a ‾ \overline{aba} aba 即长度为奇数。
那么我们只需要判断一个数中是否有这两种回文串就行了。
d p p o s , l a s t 1 , l a s t 2 , l a s t 3 , f l a g dp_{pos,last1,last2,last3,flag} dppos,last1,last2,last3,flag 表示填到第 i i i 位,前三位分别是 l a s t 1 , l a s t 2 , l a s t 3 last1,last2,last3 last1,last2,last3 时,是否满足条件的“萌数”的个数。
在转移时需要注意如果一个数已经是“萌数”时(即 f l a g = 1 flag=1 flag=1),后面无论填什么数,它的状态都不会改变。


AC Code
// Problem: P3413 SAC#1 - 萌数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3413
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Author: Li_Feiy
#include<bits/stdc++.h>
#define arrout(a,n) rep(i,1,n)std::cout<<a[i]<<" "
#define arrin(a,n) rep(i,1,n)a[i]=read()
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dep(i,x,n) for(int i=x;i>=n;i--)
#define erg(i,x) for(int i=head[x];i;i=e[i].nex)
#define dbg(x) std::cout<<#x<<":"<<x<<" "
#define mem(a,x) memset(a,x,sizeof a)
#define all(x) x.begin(),x.end()
#define arrall(a,n) a+1,a+1+n
#define PII std::pair<int,int>
#define m_p std::make_pair
#define u_b upper_bound
#define l_b lower_bound
#define p_b push_back
#define CD const doubleF
#define CI const int
#define int long long
#define il inline
#define ss second
#define ff first
#define itn int
int read() {
    char ch=getchar();
    int r=0,w=1;
    while(ch<'0'||ch>'9') w=ch=='-'?-1:w,ch=getchar();
    while(ch>='0'&&ch<='9') r=r*10+ch-'0',ch=getchar();
    return r*w;
}
CI N=1e3+5,MOD=1e9+7;
int a[N],num[N],dp[N][10][10][10][2];
std::string l,r;
int dfs(int pos,int last1,int last2,int last3,bool flag,bool st,bool limit) {
    if(pos>a[0]) {
        return flag&&!st;
    }
    if(~dp[pos][last1][last2][last3][flag]&&!st&&!limit) {
        return dp[pos][last1][last2][last3][flag];
    }
    int up=limit?a[a[0]-pos+1]:9,ans=0;
    rep(i,0,up) {
        ans=(ans+dfs(pos+1,i,last1,last2,flag/*如果已经是“萌数了”*/||((i==last1&&last1/*不为00*/&&last1!=-1/*last1填过*/)||/*存在aa前没有数且为aa形式*/(i==last1&&!last1/*为00*/&&last2/*aa前有数*/&&last2!=-1&&last1!=-1)/*存在aa前有数且为aa形式*/||(i==last2&&i!=last1&&last2/*不为0b0*/&&last2!=-1/*last2填过*/)/*存在aba前没有数且为aba形式*/||(i==last2&&i!=last1&&!last2/*为0b0*/&&last3>0/*0b0前有数*/&&last2!=-1)/*存在aba前有数且为aba形式*/),st&&!i,limit&&(i==up))%MOD)%MOD;
    }
    if(!st&&!limit) {
        dp[pos][last1][last2][last3][flag]=ans%MOD;
    }
    return ans%MOD;
}
int solve(std::string x) {
    a[0]=0;
    dep(i,x.size()-1,0) {
        a[++a[0]]=x[i]-'0';
    }
    mem(dp,-1);
    return dfs(1,-1,-1,-1,0,1,1)%MOD;
}
signed main() {
    std::cin>>l>>r;
    std::string s=l;
    dep(i,s.size()-1,0){
        if(s[i]!='0'){
            s[i]--;
            break;
        }else{
            while(s[i]=='0'&&i>=0){
                s[i]='9';
                i--;
            }
            s[i]--;
            break;
        }
    }
    if(s[0]=='0'){
        rep(i,0,s.size()-1){
            s[i]=s[i+1];
        }
        s.pop_back();
    }
    std::cout<<(solve(r)-solve(s)+MOD)%MOD;
    return 0;
}
  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值