小工具集合
小工具集合
基于项目 smilelc3/MyLittleTool
和 smilelc3/sudoku-solver,并使用
wasm
技术实现 JavaScript
调用 C/C++
和
Go
。
基于项目 smilelc3/MyLittleTool
和 smilelc3/sudoku-solver,并使用
wasm
技术实现 JavaScript
调用 C/C++
和
Go
。
某些题目,由于要计算的答案非常大(超出64位整数的范围),会要求把答案对 \(10^9 + 7\)取模。如果在计算中途没有处理得当的话,会出现WA(错误)或则TLE(超时)。
例如计算多项乘积时,如果没有中途及时取模,乘法结果会溢出(例如C/C++),从而得到非预期的答案 。对于 Python 来说,虽然没有溢出,但是大整数(big integer)之间的运算不是 \(O(1)\),可能会导致LTE。
一般涉及到取模(\(\bmod\))的题目,会用到如下两个恒等式 \[ \begin{align} (a+b) \bmod m &= ((a \bmod m) + (b \bmod m)) \bmod m \\ (a \cdot b) \bmod m &= ((a \bmod m) \cdot (b \bmod m)) \bmod m \\ \end{align} \]
证明:根据带余除法,\({\forall} a \in \mathbb{z}\),都可以表示为\(a = qm + r\ (m \neq 0)\),其中整数\(q\)为\(a\)除以\(m\)的商(quotient),整数\(r\)为\(a\)除以\(m\)的余数(remainder),即\(r = a \bmod m\)。
设\(a = q_1 m + r_1\),\(b = q_2 m + r_2\)。 第一个恒等式: \[ \begin{align} (a+b) \bmod m &= (q_1 m + r_1 +q_2 m + r_2) \bmod m \\ &=((q_1 + q_2)m + r_1 + r_2) \bmod m \\ &=(r_1 + r_2) \bmod m \end{align} \] 又因为\(r_1 = a \bmod m\),\(r_2 = b \bmod m\)有: \[ (a+b) \bmod m = ((a \bmod m) + (b \bmod m)) \bmod m \]
第二个恒等式: \[ \begin{align} (a\cdot b) \bmod m &= ((q_1 m + r_1)(q_2 m + r_2)) \bmod m \\ &= (q_1 q_2 m^2 + (q_1 r_2 + q_2 r_1)m + r_1 r_2) \bmod m \\ &=(r_1 r_2) \bmod m \end{align} \]
同样有: \[ (a\cdot b) \bmod m =((a \bmod m)\cdot (a \bmod m)) \bmod m \]
根据这两个恒等式,我们可以在计算过程中(例如循环中),对加法和乘法的结果取模,而不是在计算最终结果后再取模。
注意:如果涉及到幂运算,不能随意取模。如果指数为整数,可以用快速幂。
如果计算过程中有减法,可能会产生负数,处理不当也会导致 WA。如何正确处理这种情况呢?
首先引入同余(congruence modulo) 的概念。 两个整数\(a\),\(b\),若它们除以正整数\(m\)所得的余数相等,则称\(a\),\(b\)对于模\(m\)同余,记作: \[ a \equiv b \pmod m \]
例如\(42 \equiv 12 \pmod {10}\),因为\(42\)和\(12\)都可以被\(10\)整除,余数都是\(2\)。
对于负数,我们可以将其转化为对应的非负数再取模。例如,\(-17 \bmod 10\)可以转化为\(((-17 \bmod 10) +10) \bmod 10 = (-7 +10) \bmod 10\),结果是\(3\)。 也就是说,如果我们发现 \((x \bmod m) < 0\),可以加上一个\(m\),得到非负数。
为避免判断\(x\bmod m < 0\),可以写成 \[ (x \bmod m + m) \bmod m \]
这样无论\(x\)是否为负数,运算结果都会落在区间\([0,m−1]\)中。
如果要计算\(\frac{24}{8} \bmod 5\),如果像加法或乘法处理,写成\(\frac{24 \bmod 5}{8 \bmod 5} \bmod 5 = \frac{4}{3}\),明显不是正确答案\(3\)。先有结论:
如果\(p\)是一个质数,\(a\)是\(b\)的倍数且\(b\)和\(p\)互质,那么有 \[ \frac{a}{b} \bmod p = (a \cdot b^{p-2}) \bmod p \]
如果实际题目中推导出了包含除法的求余式,可以用上式转换成乘法,并用快速幂计算\(b^{p-2} \bmod p\)。
证明:
其中 \[ \mathrm{C}_p^i = \frac{p!}{i!(p-i)!} \] 证明:当\(p\)是质数且\(1 \leq i \leq p-1\)时,\(\frac{p!}{i!(p-i)!}\)分母一定不含\(p\),由于分子中包含\(p\)且\(\mathrm{C}_p^i\)为整数,所以\(\mathrm{C}_p^i\)一定能被\(p\)整除,即\(\mathrm{C}_p^i \equiv 0 \pmod p\)。
当\(p\)为质数,且\(x, y \in \mathbb{z}\)时,除去\(k=0\)和\(k=p\)两项,根据引理1,其余项与\(0\)关于\(p\)同余。即 \[ \sum_{k=1}^{p-1}{\mathrm{C}_p^k x^{p-k} y^k} \equiv 0 \pmod p \] 拆分 \[ \begin{align} (x+y)^p &= \mathrm{C}_p^0 x^p y^0 + \sum_{k=1}^{p-1}{\mathrm{C}_p^k x^{n-k} y^k} + \mathrm{C}_p^p x^0 y^p \\ &=x^p + y^p + \sum_{k=1}^{p-1}{\mathrm{C}_p^k x^{n-k} y^k} \end{align} \]
于是当\(p\)为质数,且\(x, y \in \mathbb{z}\)时,有: \[ (x+y)^p \equiv x^p + y^p \pmod p \]
根据费马小定律,对任意整数\(a\)和任意质数\(p\),有: \[ a^p \equiv a \pmod p \] 证明:当\(a = 0\)时,\(0^p \equiv 0 \pmod p\)成立; 已知引理2,通过归纳法,我们可以得到: \[ (x_1+ ... +x_n)^p \equiv x_1^p + ... + x_n^p \pmod p \]
如果将\(a\)展开为\(a\)个\(1\)相加,\(a=1+...+1\),代入上式有: \[ a^p \equiv (1+ ... +1)^p \equiv 1^p + ... + 1^p \equiv a \pmod p \]
根据数学归纳法,原命题对于 \(a\ge 0\) 成立。对于\(a < 0\)的情况同理,证明完毕。
如果\(a\)不是\(p\)的倍数,费马小定理也可以写成更加常用的一种形式: \[ a^{p-1} \equiv 1 \pmod p \] 如果\(a\)是\(p\)的倍数,显然有:\(a^{p-1} \equiv 0 \pmod p\)。
在\(a\)不是\(p\)的倍数的前提下,两边同时乘以\(\frac{b}{a}\),有 \[ b \cdot a^{p-2} \equiv \frac{b}{a} \pmod p \]
即 \[ \frac{b}{a} \bmod p = (b \cdot a^{p-2}) \bmod p \]
1 | // 如果取模到 [0, MOD-1] 中,无论正负 |
RTL8367S-CG
二层管理 5+2 端口 10/100/1000M 交换机控制器
概述
RTL8367S-CG 是一款 LQFP-128 封装的高性能 5+2 端口 10/100/1000M 以太网交换机,具有低功耗集成 5 端口 Giga-PHY,支持 1000Base-T、100Base-TX 和 10Base-T传输标准。
对于特定应用,RTL8367S 支持一个额外的接口,可配置为 RGMII/MII 接口。 RTL8367S 还支持一个可配置为 SGMII/HSGMII 接口的 Ser-Des 接口。 RTL8367S集成了高速交换机系统的所有功能;包括用于数据包缓冲的 SRAM、无阻塞交换结构以及单个 CMOS 器件中的内部寄存器管理。
特点
单芯片 5+2 端口 10/100/1000M 无阻塞交换架构
嵌入式 5 端口 10/100/1000Base-T PHY
每个端口支持全双工 10/100/1000M 连接(半双工仅在 10/100M 模式下支持)
额外接口(扩展 GMAC1)支持
SGMII (1.25GHz) 接口
HSGMII (3.125GHz) 接口
额外接口(扩展GMAC2)支持
媒体独立接口 (MII)
简化的 10/100/1000M 媒体独立接口 (RGMII)
通过 IEEE 802.3x 流量控制和背压进行全双工和半双工操作
应用
5 端口 1000Base-T 路由器,带 SGMII/HSGMII 和/或 MII/RGMII
芯片官网介绍:https://www.realtek.com/Product/Index?id=3699
RTL8367S-CG_Datasheet.pdf1
借用网件GE105Ev2的固件
https://www.netgear.com/cn/business/wired/switches/plus/gs105ev2/
网件固件.bin,大小2M。
使用烧录器(例如CH341)烧写到 spi norflash中。
固件MAC地址固定为00:00:00:00:00:01
,编辑固件中偏移地址
0x1FC000
指定MAC地址,可以随机生成MAC
在标准C语言(ANSI C)中规定不能定义长度为0的数组。标准可见 ISO 9899:2011 章节 6.7.6.2
数组长度的声明表达式中,如果表达式是一个常量表达式,它的值应该大于零。
但是,有些编译器就把0长度的数组成员作为自己的非标准扩展,例如GNU C —— Arrays of Length Zero。
1 | #include <stdio.h> |
在程序中定义一个零长度数组,sizeof()
计算出大小为0,也就是说,零长数组是不占用内存空间的。
零长度数组一般不单独使用,它常常作为结构体的最后一个成员,构成一个变长结构体。
我们定义一个结构体用于接受对端发送的所有传感器数据:
1 | typedef struct { |
当然我们也可以申请一个指针,指向紧挨SENSOR_RSP_S
结构体的下一个地址,比起指针,用零长数组有这样的优势:
使用以上定义的结构体实现以下功能:
1 | // 对rsp地址赋值 |