zoukankan      html  css  js  c++  java
  • 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
    ",((r-l+1-solve())%mod+mod)%mod);
        return 0;
    }
    
    
  • 相关阅读:
    桶排序
    向控件添加变量之后,类中多了什么?
    atan2&sin
    Bug(1)
    十六进制转化二进制[c]
    接口性能分析与优化
    记一次内存泄漏DUMP分析
    偏移二分查找
    iOS开发——自定义密码输入键盘
    iOS开发——手机号,密码,邮箱,身份证号,中文判断
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11587900.html
Copyright © 2011-2022 走看看