首页 > 其他分享 >Hetao P1391 操作序列 题解 [ 绿 ] [ 二维线性 dp ]

Hetao P1391 操作序列 题解 [ 绿 ] [ 二维线性 dp ]

时间:2024-09-15 17:37:50浏览次数:8  
标签:tmp qs 奇数 题解 P1391 括号 Hetao 操作 dp

操作序列:简单的二维 dp。

观察

我们每次操作可以让 \(x\) 变为 \(2x-1\),或者当 \(x\) 为奇数时让 \(x\) 变为 \(\frac{x+1}{2}\)。

显然,执行第一种操作,会使 \(x\) 变成奇数。

那一旦我们连续执行两次操作,\(x\) 就会变为:

\[\frac{(2x+1)-1}{2}=\frac{2x}{2}=x \]

也就是说,当 \(x\) 为奇数时,这两个操作互逆。当 \(x\) 为偶数时,无法操作。

因此,在任何时候,第一次操作的次数都要大于等于第二次操作的次数。这像极了括号匹配,任何时候左括号必须大于右括号。

其中左括号是操作 \(1\),右括号是操作 \(2\)。

dp 设计

于是我们可以先在 \(x\) 为奇数时把 \(x\) 不断执行第二种操作直到变成偶数,相当于往栈里丢了几个左括号。

然后接下来我们对每次操作考虑,定义 \(dp_{i,j}\) 表示考虑前 \(i\) 位,目前栈里有 \(j\) 个左括号的方案数。

然后很显然的转移:

\[dp_{i,j}=\sum_{j=1}^{n+s}dp_{i-1,j-1}+\sum_{j=0}^{n+s-1}dp_{i-1,j+1} \]

其中 \(s\) 表示一开始加进栈里面的左括号个数。

时间复杂度 \(O(n^2)\),可过。

其实这题可以用滚动数组优化,但是不用滚动数组仍然可以过。因为我懒,就不写滚动数组了。

特判

注意到当最后 \(x\) 能变成 \(1\) 时,无论何时使用操作 \(1\) 或者操作 \(2\) 都可以。于是此时答案就是 \(2^n\)。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const ll mod=998244353;
ll dp[5005][6005],n,s,ans=0;
int main()
{
	freopen("op.in","r",stdin);
	freopen("op.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>s;
	int tmp=s,qs=0;
	while(tmp%2==1&&tmp>1)
	{
		tmp=(tmp+1)/2;
		qs++;
	}
	if(tmp!=1)
	{
		dp[0][qs]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=6000;j++)
			{
				dp[i][j]=(dp[i-1][j-1]+dp[i][j])%mod;
			}
			for(int j=0;j<=6000;j++)
			{
				dp[i][j]=(dp[i][j]+dp[i-1][j+1])%mod;
			}
		}
		for(int i=0;i<=6000;i++)ans=(ans+dp[n][i])%mod;
		cout<<ans%mod;
		return 0;
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++)dp[i][0]=(dp[i-1][0]*2)%mod;
	cout<<dp[n][0];
	return 0;
}

坑点

dp 转移上限不能直接设为 \(n\),因为一开始会多丢 \(\log\) 个左括号进去。

标签:tmp,qs,奇数,题解,P1391,括号,Hetao,操作,dp
From: https://www.cnblogs.com/zhr0102/p/18415454

相关文章

  • 语言 题解
    语言题解本题其实没有什么好说的,主要是提供一种强大的,神秘的,诡异的,跑得飞快的,逆天的,唐诗的双\(\log\)做法首先考虑将答案分类,分成跨过这个语言的lca的和没跨过的对于没跨过的,可以发现就是对于每个点,求能扩展到的深度最低的节点,这个直接暴力做就是\(O(n)\)的,所以说我们直......
  • 题解:AT_pakencamp_2019_day3_d パ研軍旗
    题意简述给定\(5\)行\(N\)列的网格,每个格子有四种可能的颜色。要使网格中每一列的颜色都一样但不能是黑色,并且相邻两列的颜色不相同。问最少改变多少个格子的颜色能满足要求。思路分析为方便处理,把给定的红色、蓝色、白色、黑色分别转成数字\(1,2,3,4\)。考虑dp。不妨......
  • 题解:AT_abc371_c [ABC371C] Make Isomorphic
    题目大意有两个简单无向图,你每一次可以给第二个图添上或去掉一条边,有相应花费,问将两个图变为同构最少需要花费多少钱。思路观察数据范围,可以发现NNN非常小,可以考虑枚......
  • 「KDOI-06-S」题解
    T2树上异或题面分析树形DP题考虑一颗子树内部的某种割边方式,假设其被分为\(n\)个连通块,每个连通块的权值分别为\(a_1,a_2,\dots,a_n\),那么该子树在这种割边方式下对答案的贡献就为\(\prod_{i=1}^{n}a_i\)。因此就可以从叶子向根不断合并,求出每种割边状态的值,时......
  • 【洛谷 P1596】[USACO10OCT] Lake Counting S 题解(深度优先搜索)
    [USACO10OCT]LakeCountingS题面翻译由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个的网格图表示。每个网格中有水(W)或是旱地(.)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,......
  • Codeforces Round 972 (Div. 2) 2005C. Lazy Narek 题解
    原题链接:https://codeforces.com/contest/2005/problem/C看了教程发现都是用dp做的,在这里分享一个差不多的SPFA的思路(赛场上忘了Dijkstra不能有负边所以炸了)时间复杂度与dp同样是O(nm)形式化题意和翻译:有n个长度为m的字符串,你可以选择或不选择来拼接它们,但是不能更改字符串的......
  • 食物链题解
    双倍经验:P2024[NOI2001]食物链当问题要求维护一些对立的关系时(朋友、敌人),就可以用种类并查集实现。因为有三种关系所以并查集的数组要开三倍空间,第一倍空间存同类关系,第二倍存捕食关系,第三倍存被捕食关系。注意:一的猎物的猎物就是一的天敌,其他就可以直接并查集维护即可。注......
  • [ABC371D] 1D Country 题解
    这题,怎么说呢,\(STL\)大法好。前置芝士:lower_pound函数在结构体上的使用。那其实这题便是一个二分前缀和的水题了。结构体存储每个村庄的距离\(x\),人口\(d\)。对于每个输入的\([l,r]\)二分查找其对应的村庄,进行一次答案的统计,输出即可。代码:#include<bits/stdc++.......
  • 【LGR-200-Div.4】洛谷入门赛 #27 A-H题解
    A#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;mt19937rnd(time(0));#defineintlonglongtypedeftuple<int,int,int>tp;#definexfirst#defineysecondtypedefpair<int,int>pii;typedefpair<double,double>......
  • 题解 [ABC371G] Lexicographically Smallest Permutation(中文/English)
    本题解提供英文版,位于示例代码之后。Englishversionofthiseditorialisprovidedafterthesamplecode.官方题解竟然用Python来算高精度lcm,我来提供一个可以避免一切大整数运算的方法。考察\(u\getsP_u\)这张图的每个置换环。为了使答案字典序最小,显然需要从前往后......