OI题单
p6186
p6185
p6186
p6185
对于任意整数$a,b$,存在一对整数$x,y$,满足$ax + by = gcd(a,b)$.
1 | int gcd(int a,int b) { |
这是辗转相除法求gcd的代码。
我们可以发现当$b = 0$时,有一组$x = 1,y = 0$,使得$ax + by = a \times 1 + b \times 0 = gcd(a,b) = a$。
对于任意一组$a,b$,假设存在一对整数$x,y$使得$bx + (a % b)y = gcd(b,a % b) = gcd(a,b)$,对它变形:
$$
bx + (a % b)y = gcd(b,a % b) = gcd(a,b)\bx + (a - b \times \lfloor a / b \rfloor)y = gcd(a,b)\ya + (x - y \times \lfloor a / b \rfloor)b = gcd(a,b)
$$
所以我们有了一对$x’ = y,y’ = x - y * \lfloor a / b \rfloor$使得$ax’ + by’ = gcd(a,b)$。
1 | #include<iostream> |
上文中我们求出了一对$x_0,y_0$满足$ax_0 + by_0 = gcd(a,b)$,现在来求通解。
取一组解$(x_1,y_1)$,再任取一组解$(x_2,y_2)$,有:
$$
ax_1 + by_1 = ax_2 + by_2 = gcd(a,b)\a(x_1 - x_2) = b(y_2 - y_1)\两边同时除以gcd(a,b),设a / gcd(a,b) = a’,b / gcd (a,b) = b’\a’(x_1 - x_2) = b’(y_2 - y_1)\此时gcd(a’,b’) = 1\所以x_1 - x_2 = kb’,y_2 - y_1 = ka’
$$
关于整数$x,y$的方程$ax + by = c$有解的充要条件是$gcd(a,b)|c$。
给定一个长度为 $N$ $(N \le 1e5)$的序列 $A$ ,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小。
试计算这个最小值。
朴素DP:
状态:设$f[i]$ 表示将前 $i$ 个数分为若干段,每段和不超过 $m$ 时,最大值之和的最小值。
转移方程:
$$
f[i] = min(f[j] + max(a[j + 1],a[j + 2],……a[i])) \ \ \ \ (\sum_{k = j + 1}^na_k \le m)
$$
其中的区间最大值和区间和分别可以用ST表和前缀和完成。
复杂度$O(n^2)$.
接下来来考虑优化。
若$j$可能作为$f[i]$的唯一最优决策,那么$j$必须满足下面两个条件之一:
- $a[j]$是$a[j],a[j + 1],……,a[i]$中的最大值
- $\sum_{k = j}^i a_k > m$
证明:
若$j$对上述两个条件都不满足,那么对于决策$j - 1$:
因为$\sum_{k = j}^i a_k \le m$,所以决策$j - 1$是合法的。
同时因为$a[j]$不是$a[j],a[j + 1],……,a[i]$中的最大值,所以
$$
\max(a[j + 1],a[j + 2],……a[i]) = \max(a[j],a[j + 1],a[j + 2],……a[i])
$$
又因为$f[i]$单调不减,所以:
$$
f[j - 1] + max(a[j],a[j + 1],a[j + 2],……a[i])\le f[j] + max(a[j + 1],a[j + 2],……a[i])
$$
即决策$j - 1$比决策$j$更优或相等,所以决策$j$不会是唯一的最优决策。
对于考虑满足第二个条件的决策,我们可以预处理出$c[i]$,表示满足$\sum_{k = j}^ia_k \le m$的最小的$j$。然后对于$f[i]$,执行f[i] = min(f[i],f[c[i] - 1]+max(a[c[i]],a[c[i] + 1],a[c[i] + 2],……,a[i]))
对于考虑满足第一个条件的决策,我们可以考虑用单调队列来优化DP。
循环变量$i$,循环开始先从队头剔除不合法的决策(即状态转移中的条件)
然后将$i$入队,同时维护单调队列元素$x$的$a[x]$单调不增,保证单调队列中的决策都是可能的最优决策。
但是这样我们还是需要循环整个单调队列枚举所有决策。
接下来我们来集中解决这个问题。
我们先建立一个used数组。
我们再建立一个小根堆,其中的元素为(id,x),按x作为比较的依据。表示对于决策$id$,x表示$f[id] + max(a[id + 1],a[id + 2],……a[id])$。
每次向单调队列中插入一个新决策$j$时,同时也向堆中插入这个决策$(j,f[j] + max(a[j + 1],a[j + 2],……,a[i]))$。当从单调队列中删除一个决策$j$时,令$used[j] = 1$。以后从堆顶取数时,需要判断$used[top().id]$是否为1,若是1,需要将其弹出,重新取堆顶。
我们能这样做的一个原因在于一旦决策$j$被丢弃,以后该决策就不可能再次出现在单调队列中了。
现在我们还需要一个问题要解决:当$i$变成$i + 1$时,有可能
$$
\max(a[j + 1],a[j + 2],……,a[i]) \neq \max(a[j + 1],a[j + 2],……,a[i],a[i + 1])
$$
即对于每个$i$,我们都需要将堆中的元素重新更新一遍。
为了方便起见,我们称呼$max(a[j + 1],a[j + 2],……,a[i])$为决策$j$对于$i$的**“决策 值**,简写为$p(j,i)$。
我们观察一下何时$p(j,i) \neq p(j,i + 1)$.发现:将$i$入队后,在单调队列${q_1,q_2,……,q_s,i}$中,因为$a[q_1] \ge a[q_2] \ge …… a[i]$,所以对于决策$q_1,q_2,……,q_{s - 1}$,$p(q_1,i) = p(q_1,i + 1)$,$p(q_2,i) = p(q_2,i + 1)$,……,$p(q_{s - 1},i) = p(q_{s - 1},i + 1)$,只有$p(q_s,i)$可能不等于$p(q_s,i + 1)$.
所以$i$入队后,我们再将决策$(id = q_s,x = f[q_s]$ + $ max(a[q_s + 1],a[q_s + 2] ,……,a[i]))$重新入队,作为修正。可以发现,$max(a[q_s + 1],a[q_s + 2] ,…,a[i]) = a[i]$。
但是,决策$q_s$在堆里面原来的错误的值并没有被修改。为了解决这个问题,我们可以给堆的结构体中加一个变量$y$表示当前决策目前的”决策值”。取出堆顶的时候,如果发现堆顶决策的”决策值“不等于堆顶决策对于$i$应有的决策值时,就将该决策视为无效,重新取堆顶。
1 | #include<iostream> |
希望能够幸福地做人,合理地度日,内心安定平和,即使身处逆境也始终保持追求。同时也希望能够通过文字与各位交流这方面的经验,于苦难中彼此慰藉。
在这里选择你的选项,然后在命令行中打pytorch官网提供的命令,打完之后如果遇到了错误,那么考虑是不是你的python版本过高。访问Start Locally | PyTorch这里来确认pytorch是否支持你的python版本。
注意:两个张量如果可以广播,那么:
例如:
1 | import torch |
2.5.1 一个标量函数如何对一个向量求导?
标量 y 对 n 维列向量 $x = (x_1,x_2,…,x_n)^T$求导,其结果还是一个n维列向量,结果是$(\frac {\partial y} {\partial x_1}, \frac {\partial y} {\partial x_2} … \frac {\partial y} {\partial x_n})^T$
标量 y 对 n 维行向量 $x = (x_1,x_2,…,x_n)$求导,其结果还是一个n维行向量,结果是$(\frac {\partial y} {\partial x_1}, \frac {\partial y} {\partial x_2} … \frac {\partial y} {\partial x_n})$