算法思维训练之线性DP和构造实战演练 (2月7日)

197 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情

串(线性DP)

image.png

f[i][0]f[i][0] :表示字符串前i个字符中既没有'u'也没有's';

f[i][1]f[i][1] :表示字符串前i个字符中有'u'没有's';

f[i][2]f[i][2] :表示字符串前i个字符中含有'u'也有's';

初始化:

f[1][0]f[1][0] = 25; // 第1项不是'u',那么就有25种选择

f[1][1]f[1][1] = 1; // 第1项是'u',那么就只能是1种选择,就是'u'

f[1][2]f[1][2] = 0; // 第1项是不可能同时存在u和s,所以 f[1][2]=0f[1][2]=0

状态转移方程:

如果前i项既不含'u'也不含's',那么前i-1项也不会含'u'和's';

f[i][0]=25×f[i1][0]%MODf[i][0] = (25 × f[i-1][0])\% MOD

如果前i项含有'u'不含's',那么有两种情况

① 第i项是'u',那么:f[i1][0]f[i-1][0]

② 第i项不是'u',且要保证第i项不是's',那么就有25个选择:25×f[i1][1]25 × f[i-1][1]

把这两种情况加起来结果

如果前i项含有'u'也含有's',那么也有两种情况

① 第i项是's',那么之前有'u',转移方程就是:f[i1][1]f[i-1][1]

② 第i项不是's',第i项有26种选择,f[i1][2]×26f[i-1][2] × 26

综上所有情况如下:

f[i][0] = (25 * f[i - 1][0]) % MOD;

f[i][1] = (25 * f[i - 1][1] + f[i - 1][0]) % MOD;

f[i][2] = (f[i - 1][1] + f[i - 1][2] * 26) % MOD;

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000010;
const int MOD = 1e9 + 7;
int n, ans;
int f[N][4];
signed main()
{
	cin >> n;
	f[1][0] = 25, f[1][1] = 1, f[1][2] = 0;
	for (int i = 2; i <= n; i++) {
		f[i][0] = (25 * f[i - 1][0]) % MOD;
		f[i][1] = (25 * f[i - 1][1] + f[i - 1][0]) % MOD;
		f[i][2] = (f[i - 1][1] + f[i - 1][2] * 26) % MOD;
		ans = (ans + f[i][2]) % MOD;
	}
	cout << ans << endl;
	return 0;
}

B. 括号(构造)

image.png 题意:

本题是一个构造题,需要构造一个形如:a × b + c的形式

如:11 = 3 × 3 + 2

因为右边要形成一个2,所以将 a×b+ca×b+c 变换形式:变成 a×(b1)+c+ba × (b - 1) + c + b

这样子就能满足题意了:

举几个例子:

如果是 11 的时候: 3 × 3 + 2;

如果是 101 的时候:10 × 10 + 1;

① 求出一个 aa,使得 a2a^2 是尽可能接近 kk 的,aa = k\sqrt{k}

② 此时的 a2a^2 == kk 不一定成立,而且如果将后面全部划分给c的话,如果k == 1e9的话,会爆长度1e5

③ res:表示除去 a2a^2 之后还有多少,res=ka2res = k - a^2;

④ 从剩下的中再维护出一个 resa⌊\frac{res}{a}⌋,防止爆长度。 即:b = resa+a⌊\frac{res}{a}⌋ + a

⑤ 此时还剩下 resres % aa 的即, cc = resres % aa

综上所述: a=k,res=kaa,b=resa+a,c=res  %  aa = \sqrt{k}, res = k - a * a, b = ⌊\frac{res}{a}⌋ + a, c = res \;\%\; a

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
	int k;
	cin >> k;
	if (k == 0) {
		cout << ")(" << endl;
		return 0;
	} 
	int a = sqrt(k), res = ceil(k - (a * a)), b = res / a + a, c = res % a;
	for (int i = 1; i <= a; i++) cout << '(';
	for (int i = 1; i <= b - 1; i++) cout << ')';
	for (int i = 1; i <= c; i++) cout << '(';
	cout << ')' << endl;
	return 0;
}