dp 杂题笔记

news/2025/2/7 7:26:32/文章来源:https://www.cnblogs.com/lyas145/p/18701971

注意

本文章中的题均在蓝及以上

原题链接若没有特殊说明,默认指向 Luogu 链接。

线性 dp

Zoltan

原题链接

题意简述:

给你一个长度为 \(N\)\(N \le 2 \times 10^5\))的序列 \(A\)\(A_i \le 10^9\)),从第一个数开始,把当前数放在另一个序列 \(B\)\(B\) 序列刚开始长度为 \(0\))的左边或右边,求所有可能的 \(B\) 序列中最长严格上升子序列的长度(设为 \(M\)),以及最长严格上升子序列长度是 \(M\)\(B\) 序列个数(个数要模上 \(10^9+7\))。
注意:两个 \(B\) 序列是相同的,当且仅当每一个数加入她们的顺序一样。例如,\([1,1]\)\([1,1]\) 是可能不同的。

可以发现:在组成的新序列中,一个数 \(x\) 左边的所有的数在原序列所对应的顺序相反、右边的所有的数在原序列所对应的顺序相同

举个例子:

原序列:1 2 3 4 5 6^ - + - + +
新序列:6 5 3 1 2 4+ + + ^ - -

在新序列中,我们以 \(1\) 为中心(下面标有 ^ 的数),她左边的数下标 +、右边的数下标 -

不够清晰?在具体一点!

在新序列中 1 的左边的数。
原序列:3 5 6
新序列:6 5 3在新序列中 1 的右边的数。
原序列:2 4
新序列:2 4

这下懂了吧?

But,这有什么用呢?

这玩意用处老大了!

在新序列中,我们把 \(x\) 作为中心,那么组成这个新序列的最长严格上升子序列就会被分成两半\(x\) 左边一半,\(x\) 右边一半,可能 \(x\) 也会在最长严格上升子序列中(特殊情况 \(x=1\)\(x=N\) 不会对答案造成影响,讲完你就明白了)。左边那一半对应原序列是一个严格下降子序列,右边那一半对应原序列还是一个严格上升子序列

举个例子(在新序列中以 \(5\) 为中心)。

原序列:5 6 3 1 4 2 7^ - + +     -
新序列:4 1 3 5 6 2 7+ + ^ -   -新序列的最长严格上升子序列:1 3 5 6 7
5 左边一半:
原序列:3 1
新序列:1 3
5 右边一半:
原序列:6 7
新序列:6 7

你可能会想:能不能在原序列求个最长严格下降子序列和最长严格上升子序列,然后把她们拼成一个新序列中的最长严格上升子序列?

不错,这和正解很近了。

但是你一定会发现:如果她们有重复的元素怎么办?并且合并似乎也不太好搞。

把刚才上面的新序列中最长严格上升子序列拿来研究研究。

1 3 5 6 7
+ + ^ - -

唉?\(5\) 左边一半的最长严格上升子序列最大的数 严格小于 \(5\) 右边一半的最长严格上升子序列最小的数。对应到原序列就是:我们得到的最长严格下降子序列最大的数 严格小于 我们得到的最长严格上升子序列最小的数

但怎么用这个性质?

\(5\)(代表新序列最长严格上升子序列的中心):你是不是忘了谁?《不为谁而作的歌》

那么对于一个新序列中最长严格上升子序列的中心 \(x\),以她为起点向外扩展的最长严格下降子序列和最长严格上升子序列是一定没有重复元素的(除了 \(x\),不过这个好处理)。

注意一下 dp 肯定是在原序列上跑的。

所以,对于原序列中的每个数 \(x\),把她强制作为新序列中最长严格上升子序列的中心,令 \(f_{i,0}\)\(cnt_{i,0}\) 分别表示以 \(i\) 为结尾的最长严格上升子序列长度以及方案数,再令 \(f_{i,1}\)\(cnt_{i,1}\) 分别表示以 \(i\) 为结尾的最长严格下降子序列以及方案数,那么在所有可能的新序列中最长严格上升子序列的长度 \(M\) 就是 \(f_{i,0}+f_{i,1}-1\),减 \(1\) 是因为 \(x\) 是她们唯一一个重复的数

于是最长一个上升子序列的长度我们就求出来了!

接下来是处理最长严格上升子序列长度是 \(M\)\(B\) 序列的个数。先讨论对于一个固定的最长严格上升子序列能组成的新序列有几个,由于组成最长严格上升子序列的数的放左或放右都已经定好了,所以她们对答案没什么影响,但是其他不组成这个最长严格上升子序列的数就不一样了,她们放左或放右都行,所以对于一个固定的最长严格上升子序列能组成的新序列的个数是 \(2^{N-M}\)。不过最长严格上升子序列可能不止一个,其个数为 \(\sum\limits_{i=1}^n cnt_{i,0} \times cnt_{i,1}[f_{i,0}+f_{i,1}-1==M]\),答案就是她们俩的,即 \(2^{N-M} \times \sum\limits_{i=1}^n cnt_{i,0}*cnt_{i,1}[f_{i,0}+f_{i,1}-1==M]\)

注意代码中的一些处理细节。

码儿:

#include<bits/stdc++.h>
#define f first
#define s second
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+5,P=1e9+7;
int n,m,len,ans;
int a[N],b[N],f[N][2],cnt[N][2];
struct TreeArray{            //这是树状数组,用来进行 dp。PII c[N];int lowbit(int x) {return x&-x;}void add(int x,int p,int s) {for (int i=x;i<=m;i+=lowbit(i)) {if (p>c[i].f) {c[i]={p,s};}else if (p==c[i].f) {(c[i].s+=s)%=P;}}}PII query(int x) {PII res={0,0};for (int i=x;i;i-=lowbit(i)) {if (res.f<c[i].f) {res=c[i];}else if (res.f==c[i].f) {(res.s+=c[i].s)%=P;}}res.s=max(res.s,1);  //注意个数最少是 1,不可能没有。return res;}
}c0,c1;
inline int read() {          //快读,没啥好看的。int x=0,f=1;char c=getchar();while (!isdigit(c)) {f=(c=='-'?-1:1);c=getchar();}while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
int main() {n=read();for (int i=n;i;i--) {a[i]=b[i]=read();}sort(b+1,b+1+n);m=unique(b+1,b+1+n)-b-1;for (int i=1;i<=n;i++) {           //离散化。a[i]=lower_bound(b+1,b+1+m,a[i])-b;}
/*----------------------一整个程序的精华----------------------*/for (int i=1;i<=n;i++) {           //dp 部分。PII t0=c0.query(a[i]-1);PII t1=c1.query(m-a[i]);f[i][0]=t0.f+1;cnt[i][0]=t0.s;f[i][1]=t1.f+1;cnt[i][1]=t1.s;c0.add(a[i],f[i][0],cnt[i][0]);c1.add(m-a[i]+1,f[i][1],cnt[i][1]);}for (int i=1;i<=n;i++) {           //求个数。int L=f[i][0]+f[i][1]-1;if (L>len) {len=L;ans=1ll*cnt[i][0]*cnt[i][1]%P;}else if (L==len) {ans=(ans+1ll*cnt[i][0]*cnt[i][1]%P)%P;}}for (int i=1;i<=n-len;i++) {ans=2ll*ans%P;}
/*--------------------------------------------------------*/printf("%d %d\n",len,ans);return 0;
}

背包

SZA-Cloakroom

原题链接

题意简述:

\(n\) 件物品,每件物品都有三个属性 \(c_i\)\(a_i\)\(b_i\)
给你 \(q\) 个询问,每次询问给出三个数 \(m,k,s\),问是否可以选出一些物品使得:

  • 对于每个选出的物品 \(i\),满足 \(a_i \le m\)\(b_i > m + s\)
  • 所有选出的物品的 \(c_i\) 和恰好是 \(k\)

\(1\le n\le 1000\)\(1\le a_i<b_i\le 10^9\)\(1\le c_i\le 1000\)
\(1\le q\le 10^6\)\(1\le m\le 10^9\)\(1\le k\le 10^5\)\(0\le s\le 10^9\)

咕咕咕

区间 dp

守卫

原题链接

题意简述:

有一座山,用有 \(n\)\(n \le 5000\))个折点的折线表示(折线下方全是岩石),第 \(i\) 个折点的坐标为 \((i,h_i)\)\(1 \le h_i \le 10^9\)),且每个折点上都有一个亭子,九条可怜只会在亭子上玩,保镖也只会在亭子处监视可怜。
保镖只能向左看,称保镖在亭子 \(p\) 能看到亭子 \(q\)\(1 \le q \le p \le n\)),当且仅当亭子 \(p\) 和亭子 \(q\) 的连线不经过任何岩石或亭子。
对于每个区间 \([l,r]\)\(1 \le l \le r \le n\)),算出能监视 \([l,r]\) 中每个亭子所需要的保镖的最少数量,由于输出量很大,你只需要求出最少数量的异或和即可。

\(n \le 5000\)?这跟区间 dp 有什么关系?\(\mathrm{O}(n^3)\) 是不妥妥 TLE 到飞起吗?

因为是用神威·太湖之光进行评测的。

用凸包或单调栈?

其实我都还不会用。

首先你需要能看出来这是个 dp 题。

我们需要每个区间的答案,而这个就是区间 dp 最擅干的事,并且暴力 dp 的优化空间都挺大的。

More importantly,题目中有个非常重要的信息:保镖只能向左看(这题是 dp 的主要原因)。

所以对于一个区间 \([l,r]\)亭子 \(r\) 上必须有一个保镖,不然就没有保镖能看见亭子 \(r\) 了。

因为是区间 dp,所以状态是 \(f_{l,r}\),不用减状态或加状态。

因为 \(r\) 的特殊地位,所以我们采用这种区间 dp 方式:

for (int r=1;r<=n;r++) {for (int l=r;l>=1;l--) {for (int k=l;k<=r;k++) {//do something . . .}}
}

\(p_1,p_2,\cdots,p_{t-1},p_t\)\(l\le p_1<p_2<\cdots<p_{t-1}<p_t=r\))表示亭子 \(r\) 在区间 \([l,r]\) 中能够看到的亭子。

那么 \([p_i+1,p_{i+1}-1]\) 这个区间上所有的亭子是亭子 \(r\) 看不到的,需要再放置保镖。首先要考虑一下这个区间的右端点怎么定。你可能会疑惑:右端点直接定 \(p_{i+1}-1\) 不就行了吗?其实,\(p_{i+1}\) 也可能成为右端点!

转移方程为:

\[f_{l,r}=\sum\limits_{k=1}^t\min(\{f_{p_i+1,p_{i+1}-1},f_{p_i+1,p_{i+1}}\}) \]

当然,这是错的。

我不是故意的,我是有意的。

你想想啊,我们是不是忘了谁?

\(l\):Do you remember me?

观察方程,怎么把 \(l\) 加进去呢?

\(p_0=l-1\) 即可,\(k\) 要从 \(0\) 开始。

于是正确的暴力转移方程式为:

\[f_{l,r}=\sum\limits_{k=0}^t\min(\{f_{p_i+1,p_{i+1}-1},f_{p_i+1,p_{i+1}}\}) \]

接下来解释 \(p_{i+1}-1\) 为什么能作右端点。

例如下图就当是图吧O 表示亭子,附近的数字是编号):

1
O                   5\                  O\         3      / \      7O--------O     /   \     O2         \   /     \   /\ /       \ /O         O4         6

假设我们在处理 \([1,7]\) 区间,\(p\) 你一眼就求出来了,是。

咕咕咕

码儿:

#include<bits/stdc++.h>
using namespace std;
const int N=5005;
int n,ans;
int h[N],f[N][N];
inline int read() {int x=0,f=1;char c=getchar();while (!isdigit(c)) {f=(c=='-'?-1:1);c=getchar();}while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
double calc(int x,int y) {return 1.0*(h[x]-h[y])/(x-y);
}
int main() {n=read();for (int i=1;i<=n;i++) {h[i]=read();}for (int r=1;r<=n;r++) {ans^=(f[r][r]=1);for (int l=r-1,i=0;l;l--) {if (!i || calc(l,r)<calc(i,r)) {i=l;}ans^=(f[l][r]=min(f[l][i],f[l][i-1])+f[i+1][r]);}}printf("%d\n",ans);return 0;
}

树形 dp

Maximizing Root

原题链接(Codeforces)

题意简述:

给你一个有 \(n\)\(2 \le n \le 10^5\))个节点的树,根节点是 \(1\),每个点有一个权值 \(a_i\)\(1 \le a_i \le 1000\))。
你可以进行以下操作(可以不操作):
选择一个之前没选过的节点 \(u\),以及一个正整数 \(x\),需要满足 \(x\)\(u\) 子树内所有节点的权值的公约数,然后令 \(u\) 子树内所有的节点的权值都乘上一个 \(x\)
问在操作不超过 \(m\)\(0 \le m \le n\))次后 \(a_1\) 的最大可能值是多少?

似乎没有简多少。

先设置状态,节点编号是必须放进去的,但是一个状态感觉并不够,在加一个什么当状态呢?公约数或许是个不错的选择。

整理一下,就是:设 \(f_{u,w}\) 表示以 \(u\) 为根节点的子树中,使其所有节点的权值的公约数变为 \(w\) 的最小操作次数。

接下来是转移。

下层的操作会对上次造成影响,所以从下往上进行 dp 是非常可行的。(其实一般树形 dp 都是从下往上进行 dp,但注意只是在一般情况下)

枚举节点 \(u\) 的每一个子节点 \(v\),然后枚举以 \(u\) 为根的子树中所有节点权值可能的公约数 \(wu\),当然也要枚举一个 \(wv\) 表示以 \(v\) 为根的子树中所有节点可能的公约数。当然,\(wu\) 必须满足是 \(a_u\) 的约数,\(wv\) 必须是 \(a_v\) 的约数。

但是我们不知道 \(u\)\(v\) 是否操作过,还需要加一维吗?其实,这不——需——要。

因为每个点只能操作一次,这就能大大地方便我们的各项处理,因此状态上,我们强制节点 \(u\) 不进行操作。

转移这时候就不难了,考虑两种情况:

  • 节点 \(v\) 不进行操作:\(f_{u,wu}=\min(\{ \begin{cases} f_{v,wv} & wv \bmod wu = 0\\ +\infty & wv \bmod wu \ne 0\\ \end{cases}\}) \)
  • 节点 \(v\) 进行操作:\(\ \ \ f_{u,wu}=\min(\{ \begin{cases} f_{v,wv}+1 & wv^2 \bmod wu = 0\\ +\infty & wv^2 \bmod wu \ne 0\\ \end{cases} \})\)

这俩情况可以放在一个循环里处理。

但是这样时间复杂度是 \(\mathrm{O}(nV^2)\)\(V\) 表示 \(a_i\) 的值域)的,直接 TLE 到飞起,并且空间复杂度也不容乐观。

优化时间又到了。

上面有这么一句话(不用往上翻了):
“当然,\(wu\) 必须满足是 \(a_u\) 的约数,\(wv\) 必须是 \(a_v\) 的约数。”

所以我们没有必要\(1\) 枚举到 \(wu\)\(wv\),可以预先处理处理一下 \(1 \sim 1000\) 中每个数的约数,到时候直接枚举 \(a_u\)\(a_v\) 的约数即可,时间复杂度直接降到 \(\mathrm{O}(nd^2)\)\(d\) 表示 \(a_i\) 的约数个数,其最大值为 \(32\)),空间也没有必要浪费给不是约数的数了,\(f_{u,w}\) 被重新定义为 在以节点 \(u\) 为根的子树中,使其所有节点的权值的公约数是 \(a_u\) 的第 \(w\) 个约数(约数最好是升序的)的最少操作次数,空间复杂度猛降到 \(\mathrm{O}(nd)\)

我们设一个数 \(x\) 的第 \(i\) 个约数是 \(d_{x,i}\)

\(wu\) 的意思换成目前枚举到的 \(a_u\) 的约数是第几个,\(wv\) 的意思换成目前枚举到的 \(a_v\) 的约数是第几个。

转移方程为变为(我们用 \(d(x)\) 表示 \(x\) 的约数个数):

\[f_{u,wu}=\sum\limits_{v\in son(u)}min_{wv=0}^{d(a_v)}(\{ \begin{cases} f_{v,wv} & d_{a_v,wv} \bmod d_{a_u,wu}=0\\ +\infty & d_{a_v,wv} \bmod d_{a_u,wu}\ne 0 \end{cases} , \begin{cases} f_{v,wv}+1 & d_{a_v,wv}^2 \bmod d_{a_u,wu}=0\\ +\infty & d_{a_v,wv}^2 \bmod d_{a_u,wu}\ne 0 \end{cases} \})\]

这一优化,使我们的 dp 的时间复杂度和空间复杂度都降到了我们可以接受的范围,这简直就是一举两得、一箭双雕、every nice 啊!

答案统计时间到!

由于我们强制 \(f_{u,w}\) 中的节点 \(u\) 不进行操作,所以我们需要用一次操作来让 \(a_1\) 变大,因此我们从大到小枚举一个 \(w\),那么在第一次 \(f_{1,w} < m\) 时,答案就是 \(a_1 \times d_{a_1,w}\)(注意可能爆 int);否则是答案是 \(a_1\)。即使 \(f_{1,w} = m\) 也不行,因为没有操作可以给节点 \(1\) 用了。

并且可以发现,\(f\) 如果已经超过了 \(m\),再大也没意义了,所以可以把大于 \(m\)\(f\) 赋成 \(m+1\)

此题完~

哦,对了!注意这题有点卡常,用 memset 清空数组会超时。

码儿:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=1005,K=35;
int T,n,m;
int a[N],f[N][K];
int h[N],e[N<<1],ne[N<<1],idx=1;
vector<int> d[M];
inline int read() {          //快读。int x=0,f=1;char c=getchar();while (!isdigit(c)) {f=(c=='-'?-1:1);c=getchar();}while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
namespace lyas145{
//这个 namespace 不用管,“lyas145::函数名”就能从外面调用这里面的函数。
void add(int a,int b) {      //链式前向星。e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void clear() {               //清空。for (int i=1;i<=n;i++) {h[i]=0;for (int j=0;j<K;j++) {f[i][j]=0;}}idx=1;
}
void dfs(int u,int fa) {     //树形 dp。for (int i=h[u];i;i=ne[i]) {int v=e[i];if (v==fa) {continue;}dfs(v,u);for (int j=0;j<d[a[u]].size();j++) {int wu=d[a[u]][j];int res=m+1;for (int k=0;k<d[a[v]].size();k++) {int wv=d[a[v]][k];if (wv%wu==0) {res=min(res,f[v][k]);}//节点 v 不操作。else if (wv*wv%wu==0) {res=min(res,f[v][k]+1);}//节点 v 操作。}f[u][j]=min(f[u][j]+res,m+1);}}
}
void main() {n=read();m=read();for (int i=1;i<=n;i++) {a[i]=read();}for (int i=1;i<n;i++) {int a=read(),b=read();add(a,b);add(b,a);}dfs(1,0);for (int i=d[a[1]].size()-1;~i;i--) {if (f[1][i]<m) {printf("%lld\n",1ll*a[1]*d[a[1]][i]);return ;}}//能对节点 1 进行操作来对答案造成贡献。printf("%d\n",a[1]);//不能对节点 1 进行操作来对答案造成贡献。return ;
}
}
int main() {for (int i=1;i<=M-5;i++) {//求 1~1000 的约数。for (int j=i;j<=M-5;j+=i) {d[j].push_back(i);}}T=read();while (T--) {lyas145::main();lyas145::clear();}return 0;
}

UZASTOPNI

原题链接

题意简述:

给你一个有 \(n\)\(1 \le n \le 10^4\))个节点的树,根节点是 \(1\),并且每个节点都有一个权值 \(v_i\)\(1 \le v_i \le 100\))。
你要从中选出一些点,并满足以下条件:

  1. 一个点的父节点若未被选择,则这个点就不能被选择。
  2. 所选点的集合内不能有相同的权值。
  3. 对于每一个选择的点,其子树中所有被选择的点的权值必须可以构成公差为 \(1\) 的等差数列。
    求满足上述条件的方案个数。
    注意:这里的方案是指所选的的点的权值的集合不同的方案。

其实数据可以出得更大,\(n\) 可以到 \(10^5\)\(v_i\) 能到 \(2000\)。不过这不重要,重要的是学会这题 dp 最 NB 的优化。

一看到树,基本上就是树形 dp 了。

公差为 \(1\) 的等差数列?不就是一串连续的整数吗?形式为 \([l,l+1,\cdots,r-1,r]\)

这玩意将会是我们做这个题的基础

于是我们的 brain 会很自然地想到一个暴力(不要直接不看了,我讲暴力是有目的的):
\(f_{u,l,r}\) 表示以 \(u\) 为根节点的子树中,拼出 \([l,r]\) 这个区间的方案数。

转移怎么搞?似乎不太好搞?

这里先咕咕一下。

码儿:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5,M=105;
int n;
int a[N];
vector<int> g[N];
bitset<M> l[N],r[N];
inline int read() {int x=0,f=1;char c=getchar();while (!isdigit(c)) {f=(c=='-'?-1:1);c=getchar();}while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
bool cmp(int x,int y) {return a[x]<a[y];
}
void dfs(int u,int fa) {l[u].set(a[u]);r[u].set(a[u]);for (int v : g[u]) {if (v!=fa) {dfs(v,u);}}for (int i=0;i<g[u].size();i++) {int v=g[u][i];if (a[u]<a[v] && (r[u]<<1&l[v]).any()) {r[u]|=r[v];}}for (int i=g[u].size()-1;~i;i--) {int v=g[u][i];if (a[v]<a[u] && (l[u]>>1&r[v]).any()) {l[u]|=l[v];}}
}
int main() {n=read();for (int i=1;i<=n;i++) {a[i]=read();}for (int i=1;i<n;i++) {int a=read(),b=read();g[a].push_back(b);g[b].push_back(a);}for (int i=1;i<=n;i++) {sort(g[i].begin(),g[i].end(),cmp);}dfs(1,0);printf("%d\n",l[1].count()*r[1].count());return 0;
}



\[\huge\color{gold}\mathcal{Thanks\ for\ reading!} \]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/879914.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BOM最全基础信息:标准件、通用件、替换件、必选件

在生产制造领域,物料清单(BOM)是产品设计、生产计划和供应链管理的核心基础。本文系统梳理了BOM中各类零部件的分类方法,供大家参考。在生产制造的复杂领域中,我们会与各式各样的产品组成部分打交道。清晰、准确地对它们进行分类,并实施有效的管理,对于提升生产效率、保…

人工智能辅助芯片设计

芯片设计:一个近乎无限的问题空间 设计复杂性呈指数级增长 设计复杂性的含义 一连串棘手的问题 贯穿整个流程优化 HDL生成研究 使用GCN加速设计评估 人工智能辅助验证 参考文献链接https://www.hc2024.hotchips.org/assets/program/tutorials/3-HC24.synopsys.SteliosDiaman…

应用随机过程 | 期末 cheat sheet

出分后发布笔记……这篇博客汇总了「应用随机过程」2018 - 2022 的期末试题,并根据题型分类总结。 本站相关博客:应用随机过程 | 期末知识点总结特别鸣谢:知乎 | 九一居士 |《应用随机过程》课程笔记系列目录1 马尔可夫链计算题2 常返的马尔可夫链3 连续时间参数的马尔可夫链…

推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》4本书,非常感谢

4本书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该…

OpenVX基本原理与历史

OpenVX基本原理 2.1 引言 2.1.1 摘要 OpenVX 是一个低级编程框架域,用于支持软件开发人员,可高效访问计算机视觉硬件加速功能和性能的可移植性。OpenVX 旨在支持现代硬件架构,例如,移动和嵌入式 SoC 以及桌面系统。其中许多系统是并行和异构的:多个处理器类型包括多核 CPU…

L4D2自制角色Mod - HUI篇

如何以相对简易的思路自制求生之路2求生者头像Mod本文是笔者尝试制作 求生之路2 角色 Mod 的过程中编写的笔记,笔者的背景是有基础的计算机知识和图像处理软件的使用经验,相信大多数读者朋友都有同样的水平。本文面向希望能快速简单地自定义游戏内角色图像/模型,但对更深层次…

使用Netty与前端请求进行交互实现实时通讯

引言因为不满足与一般的SpringBoot CRUD开发(太无聊了)所以去学一下网络编程,第一站就是通过B站老罗的EasyChat项目了解到了Netty这个网络框架,在学习这个项目之前也是去学习了一下Netty框架的使用以及相关的原理知识所以是有一定了解的,但是只是一味的学习不去实践总感觉是空中…

如何使用 Filebeat 8 连接 Easysearch

在日志场景,还是有很多小伙伴在使用 Filebeat 采集日志的。今天我来实战下使用 Filebeat 8 连接 Easysearch 。本次使用 Easysearch-1.9.0 版本和 Filebeat-8.17.0 版本做演示,也适用 Filebeat-oss-8.17.0 版本。 Easysearch 不开启兼容参数的情况 Easysearch 默认情况下未开…

25.2.7小记

异常捕捉 try{} catch{} import java.util.Scanner;public class ArrayIndex {public static void main(String[] args) {int [] a =new int[10];int idx;Scanner in = new Scanner(System.in);idx = in.nextInt();try{a[idx] = 10;System.out.println("hello");}cat…

《笨办法学Python3》PDF、EPUB免费下载

本书是一本Python入门书,适合对计算机了解不多,没有学过编程,但对编程感兴趣的读者学习使用。这本书以习题的方式引导读者一步一步学习编程,从简单的打印一直讲到完整项目的实现,让初学者从基础的编程技术入手,最终体验到软件开发的基本过程。本书是基于Python 3.6版本编…

RocketMQ实战—5.消息重复+乱序+延迟的处理

大纲 1.根据RocketMQ原理分析为什么会重复发优惠券 2.引入幂等性机制来保证数据不会重复 3.如何用死信队列处理优惠券系统数据库宕机 4.基于RocketMQ的订单库同步为什么会消息乱序 5.如何解决RocketMQ的消息乱序问题 6.RocketMQ的顺序消息机制的代码实现 7.基于RocketMQ的数据过…