首页 > 其他分享 >[题解]P3413 萌数

[题解]P3413 萌数

时间:2024-04-14 11:55:06浏览次数:30  
标签:P3413 sta int 题解 pos hui stanum limit 萌数

P3413 萌数

先打出暴搜代码,参数有\(pos,limit,hui\),其中bool类型的\(hui\)表示到当前是否有回文。

暴搜代码中加入了一个剪枝:if(!limit&&hui) return pow10[pos];,这个!limit很重要,我就是因为这个没加,暴搜代码都调了半天。然后就是if(pos==0) return hui;

我们还需要记录下填过的位是不是前导\(0\),所以用-1表示前导\(0\)。

接下来考虑怎么记忆化,我们发现,当前的答案只和\(pos\)、\(sta[pos+1]\)和\(sta[pos+2]\)有关。我们在\(pos\)相同的情况下分类讨论:

  • 后\(2\)位都不是前导\(0\),而且都不一样。
  • 后\(2\)位都不是前导\(0\),而且都一样。
  • 后\(2\)位中最高位是前导\(0\)。
  • 后\(2\)位中都是前导\(0\)。

我们又可以发现,第\(2\)种情况和第\(3\)中情况本质上是一样的。所以\(pos\)相同的时候,一共只有\(3\)中情况,我们根据情况计算出状态码,然后用\(f[pos][stanum]\)来记忆化。空间和时间都很优,\(1010*3\)。

注意

  • \(L,R\)足足有\(1000\)位,所以得用string存。而字符串减\(1\)操作不好弄,所以答案用\(solve(r)-solve(l)\),然后特判\(l\)是否符合条件,符合条件再额外加\(1\)。
  • 虽然不需要开long long,但是打表计算\(pos10\)的时候需要类型转换一下再取模,否则\(*10\)会溢出。

Code

点击查看代码
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
string l,r;
int a[1010],sta[1010],len;
int f[1010][3],pow10[1010];
int dfs(int pos,bool limit,bool hui){
	if(!limit&&hui) return pow10[pos];
	if(pos==0) return hui;
	int stanum;
	if(sta[pos+1]==-1&&sta[pos+2]==-1) stanum=2;
	else if(sta[pos+2]==-1||sta[pos+1]==sta[pos+2]) stanum=1;
	else stanum=0;
	if(!limit&&f[pos][stanum]!=-1) return f[pos][stanum];
	int rig=limit?a[pos]:9,ans=0;
	for(int i=0;i<=rig;i++){
		bool is=(sta[pos+1]==-1&&i==0);
		sta[pos]=is?-1:i;
		bool thui=hui||(sta[pos]==sta[pos+1]&&sta[pos+1]!=-1)||(sta[pos]==sta[pos+2]&&sta[pos+2]!=-1);
		ans=(ans+dfs(pos-1,limit&&i==rig,thui))%mod;
	}
	if(!limit) f[pos][stanum]=ans;
	return ans;
}
int solve(string s){
	len=s.size();
	for(int i=0;i<len;i++){
		a[len-i]=s[i]-'0';
	}
	sta[len+1]=sta[len+2]=-1;
	return dfs(len,1,0);
}
int main(){
	pow10[0]=1;
	for(int i=1;i<=1005;i++) pow10[i]=(10ll*pow10[i-1])%mod;
	memset(f,-1,sizeof f);
	cin>>l>>r;
	bool is=0;
	int len=l.size();
	for(int i=0;i<len-2;i++){
		if(l[i]==l[i+1]||l[i]==l[i+2]){
			is=1;
			break;
		}
	}
	if(l[len-2]==l[len-1]) is=1;
	cout<<(solve(r)-solve(l)+is+mod)%mod;
	return 0;
}

标签:P3413,sta,int,题解,pos,hui,stanum,limit,萌数
From: https://www.cnblogs.com/Sinktank/p/18133932

相关文章

  • [题解]CF55D Beautiful Numbers
    CF55DBeautifulNumbers打出暴搜后有些茫然,不知道该怎么优化才好,看了题解才豁然开朗。简单说下暴搜的思路:参数有\(pos,limit,lcm,num\)。其中\(lcm\)表示到\(pos+1\)位,所有非\(0\)位的\(lcm\)是多少;\(num\)表示填到\(pos+1\)位的整个数是多少。然后在\(pos=0\)时判断\(lcm\)是......
  • [题解]CF1073E Zegment Sum
    CF1073ESegmentSum这道数位dp与其他不同的是,这个求的是满足要求的数的和,这种题型的题我们还没有做过。以前虽然做过一些求和或者求积的题,但都是求每个满足条件的数的数位和、二进制1的个数等等的和。而这道题是对\([L,R]\)中满足条件的数直接求和,这意味着基本不会有两个状态得......
  • [NOIP2018] 旅行 题解
    明显要以\(1\)为起点。原图是树这种情况下,走路不能回头,只能用\(dfs\)的思路走。当然肯定每次都走较小的那棵子树,\(vector\)存图后排序即可达到这种效果。时间复杂度\(O(n\logm)\)。原图是基环树明显可以分别考虑将所有边断掉后的情况,取字典序最小的。时间复杂度\(O(......
  • CF382B Number Busters 题解
    总共就两种情况。当\(b\geqx\)时,\(b\)要减\(x\),\(c\)要减去一。当\(b\ltx\)时,\(a\)和\(c\)都要减一,\(b=w-x\)。如果\(c>a\),退出循环。每一次循环判断\(b\)跟\(x\)的关系,然后秒数加一。代码:#include<bits/stdc++.h>usingnamespacestd;inta,b,c,w,x;in......
  • CF455C Civilization 题解
    思路求树的直径,并存在一个数组里。用并查集来动态合并加维护区域信息(包括同一颗树里的有着相同祖先的点的合并,不同树之间的合并)。假设\(length\)数组:对于每棵树的根节点\(x\),\(length_{x}=\)该树的直径长度接下来对于每个询问(如果给出的两点在同一颗树内则忽略),利用并查......
  • [题解]SP10606 Balanced Numbers
    SP10606BalancedNumbers关于优化方式的说明详见数位dp例题及详解-下。SPOJ注册不上所以暂时无法提交w,但是3份代码与正解对拍没有问题。使用\(vis[0\sim9]\)表示\(0\sim9\)的访问情况,\(sta[0\sim9]\)表示\(0\sim9\)填写个数的奇偶性(奇数为\(1\),偶数为\(0\))。暴搜先打出来,......
  • 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解
    试题A:握手问题本题总分:\(5\)分思路:组合计数,用为\(50\)个人握手的总方案数\(C^{2}_{50}\),减去七个人彼此没有握手握手的方案数\(C^{2}_{7}\)即为答案。A:握手问题#include<bits/stdc++.h>#defineintlonglong#definedblongdouble#defineall(f)f.begin()......
  • CF1923B Monsters Attack! 题解
    题目简述数轴上有$n$个怪兽。最初第$i$个怪兽在$x_i$位置上,且血量为$a_i$。你在位置$0$上。在每秒钟会发生:你给任意怪兽发射总共$k$颗子弹,受到攻击的怪兽血量减一。血量小于等于$0$的怪兽死亡。没有死亡的怪兽向你移动一个单位。当一个怪兽来到你的位置,你就输......
  • CF1165E Two Arrays and Sum of Functions 题解
    题目简述已知两个长度均为$n$的数组$a$和$b$。给定一个函数:$f(l,r)=\sum\limits_{l\lei\ler}a_i\cdotb_i$。你的任务是对数组$b$中的元素以任意的顺序重新排序,使$\sum\limits_{1\lel\ler\len}f(l,r)$的值最小。题目分析我们首先进行化简,发现题......
  • CF107A Dorm Water Supply 题解
    题目简述给出一个$n$个点,$m$条边的有向图,边带权。保证每个点的出度和入度最多为$1$。对于每一个入度为$0$,出度为$1$的点,我们在该点建一个水箱。对于每一个入度为$1$,出度为$0$的点,我们在该点建一个水龙头。可以发现,每一个水箱对应一个唯一的水龙头,我们将每对对应......