commit afc6b6349ddc584e7afab7c8165b46b5b80ab177 Author: szdytom Date: Fri Apr 21 10:40:46 2023 +0800 初始化与前四个问题 Signed-off-by: szdytom diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0aa678c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pdf +*.exe \ No newline at end of file diff --git a/assets/p4-bipart.svg b/assets/p4-bipart.svg new file mode 100644 index 0000000..d1c1980 --- /dev/null +++ b/assets/p4-bipart.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/p4-explain.svg b/assets/p4-explain.svg new file mode 100644 index 0000000..5a52cf7 --- /dev/null +++ b/assets/p4-explain.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/p5-explain-bad.svg b/assets/p5-explain-bad.svg new file mode 100644 index 0000000..09f4a87 --- /dev/null +++ b/assets/p5-explain-bad.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/p5-explain-bad.txt b/assets/p5-explain-bad.txt new file mode 100644 index 0000000..0746bd6 --- /dev/null +++ b/assets/p5-explain-bad.txt @@ -0,0 +1,21 @@ +OutputFile="p5-explain-ok.svg" +R=.1 +Thickness=.01 +BorderColor="#616161" +ColorMap:r="#FF7043" +ColorMap:b="#29B6F6" +Xaxis="right" +Yaxis="Down" +--- +6 +1 -1 b +2 -2 b +1 -2 b +2 -1.5 r +1.5 -.5 r +2.5 -1 r + +3 +1 4 +3 5 +2 6 \ No newline at end of file diff --git a/assets/p5-explain-ok.svg b/assets/p5-explain-ok.svg new file mode 100644 index 0000000..8c3858b --- /dev/null +++ b/assets/p5-explain-ok.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/p5-explain-ok.txt b/assets/p5-explain-ok.txt new file mode 100644 index 0000000..ecb16c1 --- /dev/null +++ b/assets/p5-explain-ok.txt @@ -0,0 +1,21 @@ +OutputFile="p5-explain-ok.svg" +R=.1 +Thickness=.01 +BorderColor="#616161" +ColorMap:r="#FF7043" +ColorMap:b="#29B6F6" +Xaxis="right" +Yaxis="Down" +--- +6 +1 -1 b +2 -2 b +1 -2 b +2 -1.5 r +1.5 -.5 r +2.5 -1 r + +3 +3 4 +2 6 +1 5 \ No newline at end of file diff --git a/lib.typ b/lib.typ new file mode 100644 index 0000000..02df0da --- /dev/null +++ b/lib.typ @@ -0,0 +1,44 @@ +#import "template.typ": * + +#let pagebreak_until_odd() = locate(loc => { + pagebreak() + locate(loc => if calc.even(thispage_number(loc)) { + skip_footer.update(true) + pagebreak() + skip_footer.update(false) + }) +}) + +#let italic(body) = text(style: "italic", body) + +#let type_icon(name, color) = square(size: 45pt, fill: rgb(color))[ + #set text(22pt, white, font: "Arial", weight: "regular") + #set align(center + horizon) + #name +] + +#let combinatorics_icon = type_icon("C", "FBC02D") +#let algebra_icon = type_icon("Al", "EC407A") +#let analysis_icon = type_icon("An", "FFA000") +#let number_thoery_icon = type_icon("N", "2E7D32") +#let logic_icon = type_icon("L", "000000") +#let geometry_icon = type_icon("G", "283593") + +#let bf(x) = {$upright(bold(#x))$} + +#let hypergeometric-func(ax, bx, x) = {$upright(F)lr((mat(delim: #none, ax;bx)#h(5pt)#line(angle: 90deg, length: 40pt)#h(5pt)#x))$} + +#let transpose = {$upright(sans(T))$} + +#let frange = {$op("range")$} +#let dimrange = {$op("dim range")$} + +#let theme_blue = rgb("29B6F6") +#let theme_red = rgb("FF7043") +#let theme_border = rgb("616161") +#let theme_black = rgb("212121") + +#let math_numbering(body) = { + set math.equation(numbering: "(1)") + body +} \ No newline at end of file diff --git a/main.typ b/main.typ new file mode 100644 index 0000000..b604a43 --- /dev/null +++ b/main.typ @@ -0,0 +1,525 @@ +#import "template.typ": * +#import "lib.typ": * + +#show: project.with( + title: "杂题选讲", +) + +#pagebreak() + +#align(center, + table( + columns: 6, + stroke: none, + ..for (name, fig) in ( + "组合": combinatorics_icon, + "代数": algebra_icon, + "分析": analysis_icon, + "数论": number_thoery_icon, + "几何": geometry_icon, + "数理逻辑": logic_icon + ) { + (stack(dir:ttb, fig, box[ + #set text(10pt) + #name + ], spacing: 4pt),) + } + ) +) + +#let problem_type = state("problem_type", ()) + +#show heading.where(level: 1): it => { +problem_id.step() +footer_title.update(it.body) +block(width: 100%)[ + #place( + right + top, + dx: -5pt, + dy: -5pt, + stack( + dir: ltr, + spacing: 4pt, + ..for t in problem_type.at(it.location()) { + (t,) + } + ) + ) + #set text(weight: "light", font: cnfont) + #block[ + #set text(2em) + \##problem_id.display("1") + ] + #block(fill: rgb("B3E5FC"))[ + #set text(1.5em) + #h(.3em) + #it.body + ] + #v(25pt) +]} + + + +#pagebreak_until_odd() +#problem_type.update((combinatorics_icon,)) += 随机游走的左端点 + +一个长度为 $n$ 的由 $-1$ 或 1 构成的序列 $a$,其中 1 的个数为 $c$ 个。我们称一个子区间合法是指该子区间的数的和大于等于 0。求证:所有合法子区间的左端点的数量不超过 $2c$ 个。 + +== 提示 + +子区间是指序列中连续的一段,形式化地说,问题是求证: + +$ abs(lr({l in NN[1..n] : exists l in NN[l..n],(sum_(k=l)^r a_k)>=0}))<=2c $ + +举个例子,若 $n=8,c=3$,序列 $a$ 为 + +$ -1,1,1,-1,-1,1,-1,-1 $ + +那么序列 $a$ 中所有合法子区间的左端点共有 5 个,为下面括号的位置 + +$ (-1),(1),(1),-1,(-1),(1),-1,-1 $ + +#pagebreak() + +== 解答 + +对于某个序列 $a$,记 $S(a)$ 表示序列 $a$ 中所有合法子区间的左端点的数量。 + +如果 $a$ 存在一个 $-1$ 在一个 1 的后面,即存在下标 $i,j$ 满足 $i=0$。设我们要交换序列 $a$ 中的 $i,j$ 位置,由于 $a_i=1$,所以 $p_(i-1)=p_i-1$ 。若某个位置 $k +] + +考虑 $bf(E)(min T)$ 的组合意义,可以看出它表示“首次出现 $T$ 集合中的任意一种颜色的球的时刻”,枚举这个时刻,得到 + +$ bf(E)(min T)=sum_(t\geq 0)(binom((n-abs(T))m,t)t!)/(binom(n m,t)t!)(t+1)(abs(T)m)/(n m-t) $ + +注意到这个式子只与集合 $T$ 的大小有关,而与 $T$ 中具体包含那些元素无关,因此考虑记 + +$ f(k)=sum_(t\geq 0)(binom((n-k)m,t)t!)/(binom(n m,t)t!)(t+1)(k m)/(n m-t) $ + +于是 $ bf(E)(min T)=f(abs(T)) $,代入@P2EqEmaxS1 得到, + +#[ +#show: math_numbering +$ bf(E)(max S)=sum_(T subset.eq S,T eq.not nothing)(-1)^(abs(T)-1) f(abs(T)) $ +] + +我们首先专注于解出 $f(k)$ 的简化形式,展开二项式系数并通分,得到 $f(k)=sum_(t>=0)w_t$,其中 + +$ w_t=(((n-k)m)!(n m-t)!)/(((n-k)m-t)!(n m)!)(t+1)(k m)/(n m-t) $ + +,其相邻两项的比值由 + +$ (w_(t+1))/(w_t)&=((t+2) (m n-t) (m n-t-1)! (m (n-k)-t)!)/((t+1) (m n-t-1) (m n-t)! (m (n-k)-t-1)!) +\ &=((t+2)(t+k m-n m))/((t+1-n m)(t+1)) $ + +给出,这个比值可以看成关于 $t$ 的有理函数,因此可以将原式写作超几何函数的形式: + +$ f(k)=k/n #hypergeometric-func($2, k m - n m$, $1 - n m$, 1) $ + +由组合意义可知,一定有 $k m-n m>=0$,因此可以应用范德蒙德卷积恒等式对其进行化简: + +$ f(k)&=k/n (Gamma(- 1 - k m)Gamma(1 - n m))/(Gamma(- 1 - n m)Gamma(1 - k m)) +\ &= (n m+1)/(k m+1) $ + +把这个化简后的结果代回@P2EqEmaxS2,然后再次转化为超几何函数并使用德蒙德卷积恒等式化简,可以解出 + + +$ bf(E)(max S)&=sum_(T subset.eq S,T eq.not nothing) (-1)^(abs(T)-1) (n m+1)/(abs(T)m+1) +\ &= sum_(k=1)^n (-1)^(k-1) binom(n,k)(n m+1)/(k m+1) +\ &= (1 + n m) - (1 + n m) #hypergeometric-func($1 + k m, k - n$, $1 + m + k m$, 1) +\ &= n m + 1 - ((1 / m - 1)!n!)/((n+1/m - 1)!) $ + + +注意,这个式子给出的是翻转过后的期望时刻,转化为原来问题才能得到最终答案: + +$ bf(E)=((1 / m - 1)!n!)/((n+1/m - 1)!) $ + +#pagebreak_until_odd() +#problem_type.update((algebra_icon,)) += 社团数量的上限 + +现在有 $n$ 个人要成立若干个社团(一个人可以属于多个社团)满足: + +- 每个社团的人数均为奇数; +- 任意两个不同的社团所共有的成员数量为偶数。 + +求证:所能成立的社团数量不超过 $n$ 个。 + +== 提示 + +形式化地说,记 $U={1,2,dots,n}$,已知集簇 $S subset.eq 2^U$ 满足对于任意 $A,B in S$,$abs(A sect B)$ 为奇数当且仅当 $A=B$。求证 $abs(S)<= n$。 + +容易发现,只要每个人均成立一个只包含自己的社团,就可以成立恰好 $n$ 个社团,满足每个社团的人数均为奇数(1 个),任意两个不同的社团所共有的成员数量为偶数(0 个)。 + +#pagebreak() +== 解答 + + +假设已经确定了某种成立 $m$ 个社团的方案,第 $i(1<= i<= m)$ 个社团包含的成员的集合记作 $C_i$。 + + +我们考虑一个二元域 $bb(Z)_2$,包含 ${0,1}$ 两个元素,在域上定义模 2 意义下的加法和乘法: + +#[ +#let cell_size = 30pt +#figure(stack( + dir: ltr, + spacing: cell_size, + table( + align: center + horizon, + columns: (cell_size, cell_size, cell_size), + rows: (cell_size, cell_size, cell_size), + $ + $, $ 0 $, $ 1 $, + $ 0 $, $ 0 $, $ 1 $, + $ 1 $, $ 1 $, $ 0 $, + ), + table( + align: center + horizon, + columns: (cell_size, cell_size, cell_size), + rows: (cell_size, cell_size, cell_size), + $ times $, $ 0 $, $ 1 $, + $ 0 $, $ 0 $, $ 0 $, + $ 1 $, $ 0 $, $ 1 $, + ) +), caption: [ $bb(Z)_2$ 上的加法和乘法 ]) +] + +构造 $ bb(Z)_2^(m times n)$ 上的矩阵 $A$,满足 + +$ A_(i,j)=cases(1 quad& j in C_i +\ 0 & j in.not C_i) $ + +考虑 $A A^transpose$ 这两个矩阵的乘积,是一个 $m times m$ 的矩阵,根据其第 $i$ 行第 $j$ 列的值所代表的实际意义,容易看出 + + +$ (A A^transpose)_(i,j)=cases(1 quad& abs(C_i sect C_j) mtext("是奇数") +\ 0 & abs(C_i sect C_j) mtext("是偶数")) $ + + +根据题目的约束条件,$abs(C_i sect C_j)$ 是奇数当且仅当 $i=j$,所以对角线上的数均为 1,其余位置的数均为 0,于是 + +#[ +#show: math_numbering +$ A A^transpose= bf(I)_m $ + +其中 $bf(I)_m$ 表示 $m$ 阶单位矩阵。 + +我们用 $dim V$ 表示线性空间 $V$ 的维数,$frange T$ 表示线性变换 $T$ 的值域。由于 $A$ 是 $bb(Z)_2^n->bb(Z)_2^m$ 的线性变换,其值域的维数一定满足@P2inq1[不等式]。由于 $bf(I)_m$ 是 $bb(Z)_2^m->bb(Z)_2^m$ 的线性变换,其值域的维数一定满足@P2inq2[等式]。 + + +$ dimrange A<= n $ + +$ dimrange bf(I)_m=m $ + + +另一方面,因为 $frange A A^transpose subset.eq frange A$,所以 + + +#show: math_numbering +$ dimrange A A^transpose<=dimrange A $ +] + +联立上面的@P2eq1、@P2inq1、@P2inq2、@P2inq3,就立即给出了我们欲证的结果: + +$ m=dimrange bf(I)=dimrange A A^transpose<=dimrange A<=n $ + +这表明 $m<= n$ 始终成立,原命题得证。 + +#pagebreak_until_odd() +#problem_type.update((combinatorics_icon,analysis_icon,)) += 不含三元环的最大边数 + +已知无向图 $G$ 由 $n$ 个点组成,且不包含三元环,求 $G$ 边数的最大值。 + +== 提示 + +设 $G=(V,E)$ 是一个无向图。我们称图 $G$ 中的一个“三元环”是指图 $G$ 中的三个点 $a,b,c$,满足 ${(a,b),(b,c),(a,c)} subset.eq E$。 + +例如当 $n=5$ 时,下面是一个不包含三元环的图的例子: + +#figure(image( + "./assets/p4-explain.svg", + width: 80% +), caption: [一个没有三元环的示例图]) + +该图包含 5 个点和 6 条边,可以证明所有没有三元环的由 5 个点构成的无向图的边均不超过 6 条。 + +#pagebreak() +== 解答 + +对于这种求最大值的问题,我们一般首先尝试给出一种可行的构造,再证明它是最优的。 + +把图中的 $n$ 个点分为 2 个大小尽可能的集合 $A$ 和 $B$(即大小分别为 $floor(n/2)$ 和 $ceil(n/2)$),然后对于每对点 $a in A,b in B$,在点 $a$ 和点 $b$ 之间连一条边,并且不连接其他的任何边。这样得到的图中一共连接了 $floor(n^2/4)$ 条边,且由于任意两个属于同一个集合的点之间都没有连边,这个图中不包含任何三元环。这样的图被称为“完全二分图”。 + +#figure(image( + "./assets/p4-bipart.svg", + width: 60% +), caption: [7 个点的完全二分图,包含 12 条边]) + +下面我们要证明这个构造是最优的构造,即任何由 $n$ 个点组成,不包含三元环的无向图的边数都不可能超过 $floor(n^2/4)$。这里将给出 3 种不同的证明。 + +=== 证明 A + +#[ + +#let dd = {$upright(d)$} + +设 $G=(V,E)$ 是某个无向图,包含 $n$ 个点 $m$ 条边。点 $v$ 的度数是指连接点 $v$ 的边的数量,记作 $dd(v)$。于是有 + +#[ +#show: math_numbering + +$ sum_(x in V)dd(x)=2m $ + +$ sum_(x in V)dd^2(x)=sum_((x,y)in E)dd(x)+dd(y) $ +] + +现在假设 $G$ 不包含三元环。若 $(x,y)$ 是图 $G$ 的边,那么对于任意一个点 $v$,一定有 $(x,v)in.not E$ 或 $(y,v)in.not E$,这说明 + +$ dd(x)+dd(y)<= n $ + +将这个性质代入@P4prove1eq2,得到 + +#[ +#show: math_numbering + +$ sum_((x,y)in E)dd(x)+dd(y)<= n m $ + +另一方面,对@P4prove1eq1 使用柯西-施瓦茨不等式得到 + +$ sum_(x in V)dd^2(x)>=1/n lr((sum_(x in V)dd(x)))^2=(4m^2)/n $ +] + +联立@P4prove1eq2、@P4prove1eq3、@P4prove1eq4,得到 + +$ (4m^2)/n<=sum_(x in V)dd^2(x)=sum_((x,y)in E)dd(x)+dd(y)<=n m $ + +整理得到 $m<= n^2slash 4$,注意到 $n$ 为整数,于是 $m<=floor(n^2slash 4)$,命题得证。 + +=== 证明 B + +设 $G=(V,E)$ 是某个不包含三元环的无向图,包含 $n$ 个点 $m$ 条边。两个点 $a,b in V$ 之间有连边,则称这两个点是“相邻的”,与点 $a$ 相邻的所有点构成的集合记作 $N(a)$。 + +由于 $G$ 不包含三元环,所以对于图中的任意一个点 $a$,与 $a$ 的相邻的点构成的集合 $N(a)$ 一定是独立集,即 $N(a)$ 中的任意两个都不是相邻的。 + +设 $A subset.eq V$ 是图 $G$ 中的一个最大独立集,那么对于任意一个点 $x$,一定有 + +#[ +#show: math_numbering + +$ dd(x)<=abs(A) $ +] + +令 $B=V without A$。由于 $A$ 是独立集,所以 $G$ 中的每条边都至少有一个端点包含在 $B$ 中。于是 + +$ m<=sum_(x in B)dd(x)<=sum_(x in B)abs(A)=abs(A)abs(B)<=((abs(A)+abs(B))/2)^2=(n^2)/4 $ + +其中第二个不等号使用了@P4prove2eq1,第三个不等号使用了均值不等式。注意到 $n$ 为整数,于是 $m<=floor(n^2slash 4)$,命题得证。 + +=== 证明 C + +设 $G=(V,E)$ 是某个不包含三元环的无向图,包含 $n$ 个点 $m$ 条边。考虑一个随机均匀的排列顶点排列 $sigma$,令 + +$ X={v in V:v mtext("与") sigma mtext("中所有早于") v mtext("出现的顶点相邻")} $ + +由于排列是均匀随机选择的,以及一个顶点 $x in X$ 当且仅当它出现在其所有不相邻的顶点之前,我们有 + +#[ +#show: math_numbering + +$ bf(P)(v in X)=1/(n-dd(v)) $ +] + +其中 $bf(P)(e)$ 表示事件 $e$ 发生的概率。另一方面,考虑 $X$ 的组合意义,注意到 $X$ 中的顶点集合形成一个团(图 $G$ 的子图,并且是完全图),所以一定有 $abs(X)<=2$,这给出 + +$ 2>=bf(E)(abs(X))=sum_(v in V)bf(P)(v in X)=sum_(v in V)1/(n-dd(v))>=n/(n-2m slash n) $ + +其中 $bf(E)(a)$ 表示随机试验中变量 $a$ 的数学期望。第一个等号使用了数学期望的定义,第二个等号使用了@P4prove3eq,第二个不等号利用了函数的凸性,也即琴生不等式。这个式子整理得到 $m<=n^2 slash 4$,原命题得证。 + +这个证明使用了现代组合学中的一种名为“概率方法”的技术。在这种方法中,人们以一种巧妙的方式向确定性问题中引入随机性来得到一个确定性的结果。 + +] + +#pagebreak_until_odd() +#problem_type.update((geometry_icon,)) += 无交点的匹配方案 + +平面上有红色点和蓝色点各 $n$ 个,且这 $2n$ 个点没有三个点共线。我们称一种红蓝点之间的配对方案合法,是指在每对点之间用线段连接后,得到的 $n$ 条线段没有交点。求证:一定存在一种合法的配对方案。 + +== 提示 + +形式化地说,设 $U={1,2,dots,n}$,红色点分别为 $p_1,dots,p_n$,蓝色点分别为 $q_1,dots,q_n$。一种配对方案是指 $U -> U$ 的一个双射 $f$。一种配对方案合法当且仅当线段集合 ${(p_k,q_{f(k)}):k in U}$ 中任意两条线段均不相交。 + +举个例子,对于红蓝各 3 个点的一种情况,下图为一种合法的配对方案, + +#align(center, + stack( + dir: ltr, + figure(image( + "./assets/p5-explain-ok.svg", + width: 40%, + ), caption: [一种合法方案]), + figure(image( + "./assets/p5-explain-bad.svg", + width: 40% + ), caption: [一种不合法方案]), + ) +) + +#pagebreak() +== 解答 + +红蓝各 1 个点的情况的情况是平凡的,下面均假设 $n>=2$。 + +(反证法)假设不存在一种合法的配对方案。从全部配对方案中选出连接的线段长度之和最短的一种方案,根据反证假设一定存在两条线段相交,设相交的两条线段的红色端点分别为点 $A$ 和点 $B$,蓝色端点分别为点 $C$ 和点 $D$,$A$ 和 $C$ 配对,$B$ 和 $D$ 配对,$A C$ 和 $B D$ 的交点为 $E$。 + +/* + +![交点示意图](https://s1.ax1x.com/2022/12/16/zHPDxI.png) + +根据三角形不等式,一定有 + +$$\begin{aligned}|AD|&\leq|AE|+|DE|\\|BC|&\leq|BE|+|EC|\end{aligned}$$ + +由于没有三点共线,等号一定不成立,这说明 + +$$|AD|+|BC|<|AC|+|BD|$$ + +那么 $A$ 和 $D$、$B$ 和 $C$ 配对的方案一定比这种方案线段长度之和更短,矛盾,故假设不成立。于是合法方案一定存在。 +*/ \ No newline at end of file diff --git a/scripts/g2s.cpp b/scripts/g2s.cpp new file mode 100644 index 0000000..138c653 --- /dev/null +++ b/scripts/g2s.cpp @@ -0,0 +1,96 @@ +#include + +#define N 100 + +using namespace std; + +struct vec +{ + float x,y; + void operator += (const vec &a) {x+=a.x,y+=a.y;} + void operator -= (const vec &a) {x-=a.x,y-=a.y;} + void operator *= (float a) {x*=a,y*=a;} + vec operator + (const vec &a) const {vec b=(*this);b+=a;return b;} + vec operator - (const vec &a) const {vec b=(*this);b-=a;return b;} + vec operator * (float a) const {vec b=(*this);b*=a;return b;} + float norm(){return sqrt(x*x+y*y);} +}p[N]; + +const float XL=0.1; //左边框留白比例 +const float XR=0.1; //右边框留白比例 +const float YL=0.1; //上边框留白比例 +const float YR=0.1; //下边框留白比例 +const float vertex_R=.1; //点的半径 +const float border_width=.01; //点的边框粗细 +const string border_color="#616161"; //点的边框和边的颜色 +const map mp{{"b","#29B6F6"},{"r","#FF7043"}}; //颜色映射表 + +vec calc(vec a,vec b) +{ + vec c=b-a; + c*=(vertex_R-border_width/2)/c.norm(); + return a+c; +} + +int n,m; +float minX,minY,maxX,maxY; +string pc[N]; + +void printhelp(const char* name) +{ + printf( + "g2s the 6east svg graph generator, built on %s.\n" + "Usage: %s \n" + ,__DATE__,name); + exit(1); +} + +int main(int argc,char** argv) +{ + if(argc!=3) printhelp(argv[0]); + freopen(argv[1],"r",stdin); + freopen(argv[2],"w",stdout); + cin>>n; //输入点数(int) + for(int i=1;i<=n;i++) + { + cin>>p[i].x>>p[i].y>>pc[i]; + //输入第i个点的横坐标(float)、纵坐标(float)、半径(float)和颜色(string) + if(mp.find(pc[i])!=mp.end()) pc[i]=mp.find(pc[i])->second; + if(i==1) minX=maxX=p[i].x,minY=maxY=p[i].y; + if(p[i].xmaxX) maxX=p[i].x; + if(p[i].ymaxY) maxY=p[i].y; + } + minX-=vertex_R,minY-=vertex_R; + maxX+=vertex_R,maxY+=vertex_R; + float X=minX-(maxX-minX)*XL; + float Y=minY-(maxY-minY)*YL; + for(int i=1;i<=n;i++) p[i].x-=X,p[i].y-=Y; + X=(maxX-X)+(maxX-minX)*XR; + Y=(maxY-Y)+(maxY-minY)*YR; + cout<<""<"<"<>m; //输入边数(int) + for(int i=1;i<=m;i++) + { + int a,b; + cin>>a>>b; //输入端点编号(int[1,n]) + vec A=calc(p[a],p[b]); + vec B=calc(p[b],p[a]); + cout<<""<"<, before: loc) + if numberstarter == () { + none + } else { + loc.page() - numberstarter.first().location().page() + 1 + } +} + +#let problem_id = counter("pid") + +#let project(title: "", logo: none, body) = { + set document(title: title) + set text(font: cnmainfont, lang: "zh") + set page( + width: 195mm, + height: 270mm, + margin: (top: 20mm) + ) + + show par: set block(above: 1.2em, below: 1.2em) + show heading: set text(font: cnfont, weight: "semibold") + set list(marker: (sym.square.filled.small, [--]), indent: .5em) + set ref(supplement: it => { + if it.func() == math.equation { + "式" + } else { + auto + } + }) + + set par(leading: 0.75em) + + v(0.6fr) + if logo != none { + align(right, image(logo, width: 26%)) + } + v(9.6fr) + + text(4em, weight: "light", font: cnfont, title) + v(2.4fr) + + pagebreak() + pagebreak() + + outline(depth: 1) +[ + #counter(page).update(1) + + #set page(footer: locate(loc => { + if skip_footer.at(loc) { + return + } + + let thispage = thispage_number(loc) + let is_mainpart = query(, before: loc) != () + let is_mainpart = true + let footer_content = if is_mainpart { + [\##problem_id.at(loc).first() #footer_title.at(loc)] + } + + let isleft = calc.even(thispage) + set align(left) if isleft + set align(right) if not isleft + if isleft { [#thispage] } + [ #halftab #underline(offset: 2pt, footer_content) #halftab ] + if not isleft { [#thispage] } + })) + + // Main body. + #set par(justify: true) + #set text(15pt) + + #body +] +} \ No newline at end of file