orangejuice's blog

挂了请务必叫我

「2020NOIP模拟题-广大附中」C

首先分析单对于LIS,LDS简单分析一下性质

不妨把选出的每个数 \(i,a_i\) 视为一个二维坐标系上的点,则显然在最优方案中

对于任意相邻的数,以 \((i,a_i),(i+1,a_{i+1})\) 为顶点的矩形中不存在在任何一个未被选择的点

接下来分析选出的两个序列:

推论1:两个方案的位置关系

这两个序列不论是在 \(x\) 还是在 \(y\) 上都不能被剖成两个分离的段

实际上作出两条描述方案的折线,它们必然有交点

推论2:交点的性质

只有两种情况,其中一种为

QQ截图20201119145027.png

相交的两个相邻折线,构成的矩形一定是这样的

QQ截图20201119145225.png

即分别在 \(x,y\) 上的范围有一个包含另一个

以这个交点为界,两个取出的序列值域独立,只需要找到这样的交叉处即可得到答案

接下来的问题分两步

Part1 找到候选折线

对于LIS来说一个点的转移前驱构成一个递减的子序列,显然我们需要找到这个序列中下标最小的

LDS相反

用树状数组即可

Part2 判断是否合法

满足两个维度上分别包含看起来像是一个奇怪的二维问题

但是实际上可以现,不管是LIS还是LDS,在查询的矩形中间是不会出现点的

所以可以转化为二维区间前缀问题,用离线树状数组解决

具体的,不妨对于LIS来考虑,设选出的点为 \((x,a_x),(y,a_y)\)

设候选的LDS折线为 \((u,a_u),(v,a_v)\)

我们需要知道的就是在下标上满足 \(v<y,u>x\)

在值上满足 \(a_u>a_y,a_v<a_x\)

可以分成4次查询完成,但是实际操作时和这个式子略有不同,见代码

存在两种包含关系,还需要反过来再做一次

%EI 笔记: 一类特殊的线性求和

话不多说先%%%%%EI

对于给定的常数列 \(a_i,i\in[0,n]\)

对于一些可以肉眼描述特征的多项式 \(F(x)\),以及一类特殊的 \(G(x)\)(常见的 \(G(x)\)\(e^x,a_i=i!\))。

具体的,能够对于 \(F(x)\) 列出一条较为简单的微分方程,如 \(F(x)=(1-x)F'(x)+H(x)\)

对于 \(G(x)\),容易求得 \(\sum a_i[x^i]G^k(x)\)

则可以用下面的思路求得\(\sum a_i[x^i]F(G(x))\)

Read more »

Burnside & Polya

前置知识

首先,要引入一些群论的概念,但是也不需要太懂。

如果你不想听我讲

一个集合 \(S\),我们定义两种相同,即表观相同本质相同。

称对于集合的一种操作为置换。

每一个对于集合的置换都是一种广义的对称,关于操作 \(x\) 对称的两个集合本质相同

Read more »

任意模数NTT(MTT)

模板题传送门

问题的简单描述为,求解两个值域为 \(\leq 10^9\) 的多项式卷积对于 \(P\leq 10^9\) 取模的结果。


问题不能直接用NTT/FFT求解,因为均超过了值域范围(double值域承受不了)。


Solution1:3模数NTT

取几个互质的模数分别做一次,然后用中国剩余定理合并。

由于值域大,通常需要多次 NTT,且中国剩余定理合并常数也不小。

实际代码实现也复杂,因此笔者认为不可取。


Solution2:拆系数FFT

\(f(x)=\sum a_ix^i\)

核心:将系数 \(a_i\) 分解成 \(a_i=A_i\cdot S+C_i,b_i=B_i\cdot S+D_i\)

(其中 \(S\ge \sqrt{P}\) 是一个常数, \(0 \leq A_i,B_i,C_i,D_i<S\) )。

目的是转化后使系数值域变小,double 精度可以承受。

则最后的答案转化为求解 \(A_iB_jS^2+(C_iB_j+A_iD_j)S+C_iD_j\)

即求解 \(A_iB_j,C_iB_j,A_iD_j,C_iD_j\) ,此时值域已经大大缩小。

如果直接求解,可以看出要求解4次卷积,需要进行 \(12\)FFT,不可接受。

利用复数的一些性质,有些东西我们可以一起算。

构造:

  1. \(f(x)=\sum (A_i,C_i)x^i\)

  2. \(g(x)=\sum(B_i,D_i)x^i\)

  3. \(f(x)g(x)=\sum \sum (A_iB_j-C_iD_j, A_iD_j+C_iB_j)x^{i+j}\)

此时已经得到大部分值了,再构造:

  1. \(h(x)=\sum B_ix^i\)

  2. \(f(x)h(x)=\sum \sum (A_iB_j,C_iB_j)x^{i+j}\)

取一部分即可。

最终一共有 5 次 FFT。

Tips:

1.这里的负数取整一定要注意,因为 C++ 默认是向 0 取整,而不是向下取整。

2.实际运行表明,这样写用 double 很难保证精度,应该要用 long double

附:

4次FFT做MTT,但是具体证明比较反人类,而代码非常好看且好写,所以建议直接背板子

Tips: 只要使用了上面提到的最适合FFT的板子,就可以用double,甚至可以开O2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
namespace MTT{
const double PI=acos((double)-1);
int rev[N];
struct Cp{
double x,y;
Cp(){ ; }
Cp(double _x,double _y): x(_x),y(_y){ }
inline Cp operator + (const Cp &t) const { return (Cp){x+t.x,y+t.y}; }
inline Cp operator - (const Cp &t) const { return (Cp){x-t.x,y-t.y}; }
inline Cp operator * (const Cp &t) const { return (Cp){x*t.x-y*t.y,x*t.y+y*t.x}; }
}A[N],B[N],C[N],w[N/2];

#define E(x) ll(x+0.5)%P

void FFT(int n,Cp *a,int f){
rep(i,0,n-1) if(rev[i]<i) swap(a[i],a[rev[i]]);
w[0]=Cp(1,0);
for(reg int i=1;i<n;i<<=1) {
Cp t=Cp(cos(PI/i),f*sin(PI/i));
for(reg int j=i-2;j>=0;j-=2) w[j+1]=t*(w[j]=w[j>>1]);
// 上面提到的最优板子
for(reg int l=0;l<n;l+=2*i) {
for(reg int j=l;j<l+i;j++) {
Cp t=a[j+i]*w[j-l];
a[j+i]=a[j]-t;
a[j]=a[j]+t;
}
}
}
if(f==-1) rep(i,0,n-1) a[i].x/=n,a[i].y/=n;
}

void Multiply(int n,int m,int *a,int *b,int *res,int P){
// [0,n-1]*[0,m-1]->[0,n+m-2]
int S=(1<<15)-1;

int R=1,cc=-1;
while(R<=n+m-1) R<<=1,cc++;
rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<cc);
rep(i,0,n-1) A[i]=Cp((a[i]&S),(a[i]>>15));
rep(i,0,m-1) B[i]=Cp((b[i]&S),(b[i]>>15));
rep(i,n,R-1) A[i]=Cp(0,0);
rep(i,m,R-1) B[i]=Cp(0,0);

FFT(R,A,1),FFT(R,B,1);
rep(i,0,R-1) {
int j=(R-i)%R;
C[i]=Cp((A[i].x+A[j].x)/2,(A[i].y-A[j].y)/2)*B[i];
B[i]=Cp((A[i].y+A[j].y)/2,(A[j].x-A[i].x)/2)*B[i];
}
FFT(R,C,-1),FFT(R,B,-1);

rep(i,0,n+m-2) {
ll a=E(C[i].x),b=E(C[i].y),c=E(B[i].x),d=E(B[i].y);
res[i]=(a+((b+c)<<15)+(d<<30))%P;
}
}

#undef E
}

Montgomery Reduction 算法流程与实际实现

下面默认对于模数 \(m\) 取模,由于这篇文章的重点是实现(其实就是我自己存一下板子),因此没有证明。

使用注意:

Montgomery Reduction 相较于 Barret Reduction 来说,不需要使用 __int128。

但是有着更高的封装程度,因为涉及到普通数与 Montgomery Reduction 运算中间量的转化

另外,常见的 Montgomery Reduction 在编程竞赛中的应用 要求模数为奇数

但是在 Min25 博客上来看,Montgomery 似乎有着更高的效率

在工程领域, Montgomery 用于处理大二进制数的取模问题。

Read more »

Nimber系列略学习笔记

前言

\(\text{Nim+Number=Nimber}\)

基于我们熟悉的博弈问题 \(\text{Nim}\) 问题,我们定义了多 \(\text{Nim}\) 问题的和,即 \(\text{Nim}\)

我们知道 \(\text{Nim}\) 和就是异或运算,为了构成一个更完整的 \(\text{Number}\) 域,又引入一种新的运算

\(\text{Nim}\)


Read more »

FFT&NTT(以及扩展)

预备知识:用于NTT

NTT/FFT其实本质相同,用途是快速求解 多项式乘积

前言

FT: 傅里叶变换:

这是一个工程上的概念,可以简述为:一个周期性的信号波段可以用 若干个正弦曲线 的带权和表示

DFT: 离散傅里叶变换,这是傅里叶变换在离散情况下的变种

FFT: 快速傅里叶变换

NTT: 快速数论变换

Read more »

Stirling数小记


定义/组合意义

第一类斯特林数:\(\begin{bmatrix}n\\ m\end{bmatrix}\) 表示 \(n\) 个不同元素分为 \(m\) 个圆排列的方案数。

有标号的第一类斯特林数 \(s(n,m)=(-1)^{n-m}\begin{bmatrix}n\\ m\end{bmatrix}\)

第二类斯特林数:\(\begin{Bmatrix}n\\ m\end{Bmatrix}\) 表示 \(n\) 个不同元素分为 \(m\) 个集合的方案数。

注意圆排列和集合都是相互之间无序的。



递推方法

第一类斯特林数

\(\begin{bmatrix}n\\ m\end{bmatrix}=\begin{bmatrix}n-1\\ m-1\end{bmatrix}+(n-1)\begin{bmatrix}n-1\\ m\end{bmatrix}\)

即新建一个圆排列,或者插入前面 \(n-1\) 个元素中任意一个的后面。

显然的,有标号的第一类斯特林数递推式就是:

\(\begin{bmatrix}n\\ m\end{bmatrix}=\begin{bmatrix}n-1\\ m-1\end{bmatrix}-(n-1)\begin{bmatrix}n-1\\ m\end{bmatrix}\)


第二类斯特林数:

\(\begin{Bmatrix}n\\ m\end{Bmatrix}=\begin{Bmatrix}n-1\\ m-1\end{Bmatrix}+m\begin{Bmatrix}n-1\\ m\end{Bmatrix}\)

即新建一个集合,或者加入前面的 \(m\) 个集合。



第二类斯特林数的通项公式

\(\begin{aligned} \begin{Bmatrix} n \\ m \end{Bmatrix}=\frac{1}{m!}\sum_{i=0}^{\infty} (-1)^{m-i}\binom{m}{i} i^n \end{aligned}\)

其组合意义是枚举生成了多少个有序的集合,然后容斥,最后除去集合的顺序。



生成函数表示与行/列求解

固定 \(n\),以 \(m\) 为形式幂指数,则第一类斯特林数的普通生成函数:

\(\displaystyle\text{OGF}=\prod_{i=0}^{n-1}(x+i)=x^{\overline{n}}\)

(其意义就是上面的递推公式)

倍增 + 卷积二项展开求出 \(F(x+i)\) 即可做到 \(O(n\log n)\) 求出一行。


固定 \(m\),以 \(n\) 为形式幂指数,则第一类斯特林数的指数型生成函数。

\(\begin{aligned}\text{EGF}= & \frac{1}{m!}\cdot (\sum_{i=1}^{\infty}\frac{(i-1)!}{i!}x^i)^m\\= & \frac{1}{m!}\cdot (\sum_{i=1}^{\infty}\frac{x^i}{i})^m\end{aligned}\)

\(F(x)=\sum_{i=1}^{\infty}\frac{x^i}{i}\)

\(\begin{aligned} \because F'(x)=&\sum_{i=1}^{\infty}x^{i-1}=\frac{1}{1-x}\end{aligned}\)

\(\begin{aligned} \therefore F(x)=\int \frac{1}{1-x}=-\ln(1-x)\end{aligned}\)

\(\begin{aligned}\therefore \text{EGF} = & \frac{1}{m!}\cdot (-\ln(1-x))^m\\= & \frac{1}{m!}\cdot (-1)^m\cdot \ln^m(1-x)\end{aligned}\)

(就是百度百科上的那个,它什么都没讲清楚)

多项式快速幂即可做到 \(O(n\log n-n\log ^2n)\) 求一列。


而在上式的推导过程中额外加入 \((-1)^m\) 的常数,并且把 \(x^i\) 换成 \((-x)^i\) 可以得到有标号第一类斯特林数的指数型生成函数:

\(\begin{aligned} \text{EGF} = & \frac{1}{m!}\cdot (\sum_{i=1}^{\infty}\frac{(-x)^i}{i})^m\\=& \frac{1}{m!}\cdot \ln^m(1+x)\end{aligned}\)


第二类斯特林数的一行可以直接由通项公式做卷积得到。


固定 \(m\),以 \(n\) 为形式幂指数,则第二类斯特林数的指数型生成函数表示为:

\(\begin{aligned} \text{EGF} &=\frac{1}{m!}({\sum_{i=1}^{\infty} \frac{x^i}{i!}})^m\\ &=\frac{1}{m!}(e^x-1)^m \\ &=\frac{1}{m!}\sum_{i=0}^m (-1)^{m-1} \binom{m}{i}e^{ix}\end{aligned}\)

实际上由这个二项展开的形式也可以发现,它就是上面通项公式的生成函数推导。

可以求一列,复杂度为 \(O(n\log n-n\log ^2n)\) 常数很大。

\[ \ \]

虽然没什么意义,但是还是写一下二元形式:

第一类斯特林数:

\(\begin{aligned} \text{EGF}=e^{-\ln (1-x)y}\end{aligned}\)

第二类斯特林数:

\(\begin{aligned}\text{EGF}=e^{\begin{aligned}(e^x-1)y\end{aligned}}\end{aligned}\)

注意元 \(x\) 为指数型,\(y\) 是普通型。

\[ \ \]


斯特林数与幂指数/上升幂/下降幂

第一类斯特林数:

上面已经说过 \(\begin{aligned}x^{\overline{n}}=\sum_{i=0}^{n}\begin{bmatrix}n\\i\end{bmatrix}x^i\end{aligned}\)

同理,用有标号的第一类斯特林数将 \(x^{\underline{n}}\) 展开的式子是:

\(\begin{aligned}x^{\underline{n}}=\sum_{i=0}^{n}(-1)^{n- i}\begin{bmatrix}n\\i\end{bmatrix}x^i\end{aligned}\)


第二类斯特林数:

类似通项公式的求解,组合意义将幂指数展开,视 \(x^n\) 为将 \(n\) 个元素随意放在 \(x\) 个位置,则枚举 \(x\) 个位置中哪些被选择。

\(\displaystyle x^n=\sum_{i=0}^n \binom{x}{i}i!\begin{Bmatrix}n\\i\end{Bmatrix}\)

\(\binom{x}{i}i!\) 写成下降幂的形式,得到优美的式子

\(\displaystyle x^n=\sum_{i=0}^n \begin{Bmatrix}n\\i\end{Bmatrix}x^{\underline{i}}\)


而实际上由上式二项反演也可以得到通项公式

\(\displaystyle \begin{Bmatrix} n \\ m \end{Bmatrix}=\frac{1}{m!}\sum_{i=0}^{\infty} (-1)^{m-i}\binom{m}{i} i^n\)

关于下降幂多项式的快速转化,可以再借鉴这个



斯特林变换/斯特林反演

对于斯特林变换 \(\displaystyle a_n=\sum_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}b_i\)

\(A(x),B(x)\) 为数列 \(a,b\) 的指数型生成函数,带入前文推导的式子,则得到上式的生成函数表达就是

\(A(x)=B(e^x-1)\)

显然得到 \(B(x)=A(\ln(x+1))\),而 \(\ln(x+1)\) 显然转化为有标号的第一类斯特林数。

因此得到斯特林反演的表达形式是:

\(\begin{aligned}b_n=\sum_{i=0}^{n}(-1)^{n-i}\begin{bmatrix}n\\i\end{bmatrix}a_i\end{aligned}\)

(不大可能搞类似多项式复合的方法处理这个反演吧,最多可能也就是求一个位置)

幂前缀和的生成函数

问题描述:

对于给定的大数 \(m\),求 \(\displaystyle k\in[1,n],F_k=\sum _{i=1}^m i^k\)

\(F_k=\sum _{i=1}^m i^k\),每一项的组合意义即:为 \(k\) 个元素每个染上 \(i\) 种颜色中的一个

Read more »

[水]整数拆分积

问题:对于 \(n(n\ge 3)\),要求构造拆分 \(n=\sum_{i=1}^m a_i\),最大化 \(\prod a_i\)

最优情况下,满足

  1. \(n\mod 3=0\)\(a_i=3\)

  2. \(n\mod 3=2\)\(i<m,a_i=3 ; a_m=2\)

  3. \(n\mod 3=1\)\(i<m,a_i=3 ; a_m=4\)\(i<m-1,a_i=3 ;a_{m-1}=a_m=2\)

Read more »
0%