CYW又一次去了集训,慢慢写吧,可能后续补一下里面代码模板什么的
Day0
翘了课!(划重点)来的集训,坐了下午2:00的车,结果8点半才到(火车在山东转了大半圈差评)。
下午好像学校月考,成功逃过了qwq
到了的话找小宾馆,母后大人预先找的,感觉被安排的明明白白
睡得非常早,结果错过了妹子夜里的信息(表示十分愧疚
Day1
上午考试
被虐惨了QAQ,T1是打表找规律,结果蒟蒻只打了表忘了找规律…
T2T3不是太懂,貌似都是dp
传送门
机房的AD钙真不错咕咕咕
下午上课
是何中天巨佬给我们上课,前面讲题感觉有的太快了听不懂qaq
课表内容是他们给我的,但是我觉得太简单了没必要讲,所以今天的课主要是举几个有意思的例子活跃下气氛
主要讲的是汉诺塔(外加各种变形),高精度,直线分割平面
1. 裸汉诺塔
$f[1]=1;f[2]=3;$
...
$f[n]=2(f[n-1])+1=...=2^n-1$
######2. 只能在相邻柱移动,不能A-C直达
f[1]=2;
f
[
1
]
=
2
;
移动步骤为:
- (n−1) ( n − 1 ) 个盘子 A->B , B->C
- n n 号盘子 A->B
- 个盘子,C->B , B->A
- n n 号盘子 B->C
- 个盘子,A->B , B->C
考虑1 3 4号步骤,所需步数为
f[n−1]
f
[
n
−
1
]
,则
f[n]=3(f[n−1])+2=3n−1
f
[
n
]
=
3
(
f
[
n
−
1
]
)
+
2
=
3
n
−
1
######3. Alice和Bob在玩汉诺塔,需要让Alice设计初始状态和目标状态,使得移动步数最大
emmmm不会证明,但是每一种初始状态和目标状态都被包含在“原始状态−>末状态”中,所以原始状态(A柱上n个盘子)移动到末状态(C柱上n个盘子)的步数最大 e m m m m 不 会 证 明 , 但 是 每 一 种 初 始 状 态 和 目 标 状 态 都 被 包 含 在 “ 原 始 状 态 − > 末 状 态 ” 中 , 所 以 原 始 状 态 ( A 柱 上 n 个 盘 子 ) 移 动 到 末 状 态 ( C 柱 上 n 个 盘 子 ) 的 步 数 最 大
######4. 给定初始状态和目标状态,求步数
考虑从无序状态至有序状态,再对称地至无序状态
其中有序状态指盘子按顺序依次放在柱子上
int solve(int *a, int n, int t) {
while (n && a[n] == t) n --;
if (!n) return 0;
int x = 6 - a[n] - t;
return solve(a, n - 1, x) + 1 + s[n - 1];
}
int main()
{
while (a[n] == b[n]) n --;
int t = 6 - a[n] - b[n];
ans = solve(a, n - 1, t) + 1 + solve(b, n - 1, t);
ans = min(ans, solve(a, n - 1, b[n]) + 1 + s[n - 1] + 1 + solve(b, n - 1, a[n]));
}//至于部分的n,是柱子上最大的盘子编号,所以可能编译会挂
其中 a[] a [ ] 内的元素为1,2,3,表示珠子编号, s[n] s [ n ] 表示有序时的步数,即 2n−1 2 n − 1
平面相交
f[1]=2;
f
[
1
]
=
2
;
f[n]=f[n−1]+n=1+n(n+1)2
f
[
n
]
=
f
[
n
−
1
]
+
n
=
1
+
n
(
n
+
1
)
2
推理:每一条直线与之前最多产生n个交点,所以多了n个平面
变形:n个 > > 形划分平面?
考虑延长为两条直线,所以有3个平面合并为了一个,相当于少了2个平面
快速幂
递归不上了,上一下非递归代码,用来卡常数
ll power(ll x, int y) {
ll z = 1;
while (y) {
if (y & 1) (z *= x) %= mod;
(x *= x) %= mod; y >>= 1;
}
return z;
}
高精度
老师给的板子好神啊,我没有这么写过结构体(因为太菜不敢写)
但是好像定义什么的比较奇怪,但是有的地方比较神奇,写起来方便
上板子了,不敢讲太多
struct bign {
int n[N], l;
bign() { memset(n, 0, sizeof(n)), l = 0; }
void cl() { memset(n, 0, sizeof(n)), l = 0; }
int& operator[] (int i) { return n[i]; }
void rd() {
scanf ("%s", sn + 1);
int k = 1, ls = strlen(sn + 1);
Rep(i, 1, ls) {
n[l] += (sn[ls - i + 1] - '0') * k, k *= 10;
if (i % 4 == 0 || i == ls) l ++, k = 1;
}
l --;
}
void pr() {
int len = 0;
Rep(i, 0, l) {
int k = n[i];
Rep(j, 1, 4) sn[++ len] = '0' + k % 10, k /= 10;
}
while (len > 1 && sn[len] == '0') len --;
Dwn(i, len, 1) printf("%c", sn[i]);
puts("");
}
} ans, sum;
bign make(LL x) {
bign a;
while (x) a[a.l ++] = x % lm, x /= lm;
if (a.l) a.l --;
return a;
}
bign operator+ (bign a, bign b) {
bign c = a; c.l = max(a.l, b.l);
Rep(i, 0, c.l) {
c[i] += b[i];
c[i + 1] += c[i] / lm, c[i] %= lm;
}
while (c[c.l + 1]) c.l ++, c[c.l + 1] += c[c.l] / lm, c[c.l] %= lm;
return c;
}
bign operator- (bign a, bign b) {
bign c = a;
Rep(i, 0, c.l) {
c[i] -= b[i];
if (c[i] < 0) c[i] += lm, c[i + 1] --;
}
while (c.l && !c[c.l]) c.l --;
return c;
}
bign operator* (bign a, bign b) {
bign c; c.l = a.l + b.l;
Rep(i, 0, a.l) {
Rep(j, 0, b.l) {
c[i + j] += a[i] * b[j];
//c[i + j + 1] += c[i + j] / lm;
//c[i + j] %= lm;
}
}
Rep(i, 0, c.l) c[i + 1] += c[i] / lm, c[i] %= lm;
while (c[c.l + 1]) c.l ++, c[c.l + 1] += c[c.l] / lm, c[c.l] %= lm;
return c;
}
bign operator+ (bign a, LL x) { return a + make(x); }
bign operator- (bign a, LL x) { return a - make(x); }
bign operator* (bign a, LL x) { return a * make(x); }
bign operator/ (bign a, LL b) {
bign c; LL d = 0;
c.l = a.l;
Dwn(i, a.l, 0) d = d * lm + a[i], c[i] = d / b, d %= b;
while (c.l && !c[c.l]) c.l --;
return c;
}
今天的上课就没了
晚上自习cyw刷了几道二分,写了写博客
可能回去没时间补作业了qaq
DAY2
上午
素数
1. 个数无限定理
2. 基本分解定理
n=∏ki=1prii
n
=
∏
i
=
1
k
p
i
r
i
3. 判定:
对每个x,试除
<=x−−√
<=
x
<script type="math/tex" id="MathJax-Element-18"><=\sqrt{x}</script>的素因子即可(提前预处理)
复杂度
O(x−−√/ln(x))
O
(
x
/
l
n
(
x
)
)
4. 质因数分解
5. 约数个数
S=∏ki=1(ri+1)
S
=
∏
i
=
1
k
(
r
i
+
1
)
6. 筛法
裸筛 O(NlogN) O ( N l o g N )
线性筛 O(N) O ( N )
vis[1]=1;
for (int i=2;i<=n;i++){
if (!vis[i]) pri[++cnt]=i;
for (int j=1;j<=cnt;j++){
if (i*pri[j]>n) break;
vis[i*pri[j]]=1;
if (i % pri[j]==0) break;//保证一个数只被其最小素因子筛掉
}
}
Eg1:
给定N
(N<=1000)
(
N
<=
1000
)
个数
x(x<=109)
x
(
x
<=
10
9
)
,问你是不是素数;
暴力用上法判素即可
Eg2:
给定
L,R<=109
L
,
R
<=
10
9
,求
[L..R]
[
L
.
.
R
]
内的所有素数
有同学说也可以暴力做并且给出了复杂度证明
(因为连续区间,筛去很多数时质因子跑不满就退了,所以理论复杂度高,实际还是可以过qwq)
老师:先线性筛出
[1..r√]
[
1..
r
]
内的素数,
再暴力上去做,复杂度同一般筛:
O(NlogN)
O
(
N
l
o
g
N
)
for (int i=1;i<=cnt;i++){
int p=pri[i];
for (int j=(l-1)/p+1;j<=r;j++) vis[j*p-l]=1;
}
最大公约数
GCD递归定理:
对于任意非负整数a和正整数b,Gcd(a,b)=Gcd(b,a mod b)
int gcd(int x,int y){return !y?x:gcd(y,x%y);}//log级
裴蜀定理
若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。
- a与b的线性组合集中最小的正元素为gcd(a,b)
推论
- 若
a
a
b
b
,则
a|gcd(b,c)
a
|
g
c
d
(
b
,
c
)
- a,b互质的充要条件时,存在整数x,y,使得
ax+by=1
a
x
+
b
y
=
1
- 若a|bc,且gcd(a,b)=1,则a|c
算术基本定理
存在性和唯一性(证明被吃了)
两个数相乘等价于对应质因子指数相加
gcd(a,b)=k,kp=min(ap,bp)
g
c
d
(
a
,
b
)
=
k
,
k
p
=
m
i
n
(
a
p
,
b
p
)
lcm(a,b)=w,wp=max(ap,bp)
l
c
m
(
a
,
b
)
=
w
,
w
p
=
m
a
x
(
a
p
,
b
p
)
Eg:三个未知数
x,y,z
x
,
y
,
z
,他们的
gcd
g
c
d
为
G
G
,为
L
L
,已知,求三元组个数
对每个素因子单独处理
设素因子为p,L分解式中p的指数为l,G分解式中p的指数为g,显然当
l<g
l
<
g
时不满足三元组,则我们需要
min(xp,yp,zp)=g,
m
i
n
(
x
p
,
y
p
,
z
p
)
=
g
,
max(xp,yp,zp)=l
m
a
x
(
x
p
,
y
p
,
z
p
)
=
l
则当l>=g时,若l=g则只有1种,若l>g则有6(l-g)种
扩欧
int exgcd(int a,int b,int &x,iny &y){
int d;
return !b?(x=1,y=0,a):(d=exgcd(b,a%b,y,x),y-=(a/b)*x);
}
设 (x0,y0) ( x 0 , y 0 ) 是不定方程ax+by=m的一组解,(a,b)=g,那么全部解为 (x0+(b/g)t,y0−(a/g)t) ( x 0 + ( b / g ) t , y 0 − ( a / g ) t ) ,其中 t 为所有整数
Eg1
求关于x的同余方程
ax≡1
a
x
≡
1
/的最小正整数解
其实是求逆元qwq
Eg2
【POJ1061】青蛙的约会
-1s
【NOI2002】荒岛野人
sb的cyw居然想出了正解…
枚举每一个M,对于每两个野人,当M成立时,一定有
C[i]+x⋅P[i]≡C[j]+x⋅P[j]
C
[
i
]
+
x
·
P
[
i
]
≡
C
[
j
]
+
x
·
P
[
j
]
(mod
(
m
o
d
M)
M
)
无解或最小解
>min(l[i],l[j])
>
m
i
n
(
l
[
i
]
,
l
[
j
]
)
所以暴力
N2
N
2
枚举两个野人,
exgcd
e
x
g
c
d
判断就可以了
理论复杂度
O(MlogM⋅N2)
O
(
M
l
o
g
M
·
N
2
)
但是
N2
N
2
跑不满,所以实际上能过去
逆元
//O(N)预处理逆元
q[1]=1;
for (int i=2;i<=n;i++) q[i]=q[i-1]*i%Mod;
p[n]=power(q[n],mod-2);
for (int i=n;i>1;i--) p[i-1]=p[i]*i%Mod;
剩余类
把%M同余的数归为一类,及剩余类,故共有M个剩余类
剩余系
把每一类取一个代表扔进去,叫做M的完全剩余系
M个整数构成M的剩余系当且仅当这些数两两%M不等
Eg1
f[0]=0
f
[
0
]
=
0
,当
n>1
n
>
1
时,
f[n]=(f[n−1]+a)mod
f
[
n
]
=
(
f
[
n
−
1
]
+
a
)
m
o
d
b
b
这个数列有什么特征?
按的周期循环
Eg2:费马小定理
ap−1≡1(modp)
a
p
−
1
≡
1
(
m
o
d
p
)
当p为质数且a不为p的倍数
逆定理是错的 但是可以逆否.
Eg3:二次探测定理-Miller·Rabin
若
p
p
为素数,为正整数,且
x2
x
2
mod
m
o
d
p=1
p
=
1
那么
x≡±1(mod
x
≡
±
1
(
m
o
d
p)
p
)
上午的课就没了 歇会
下午
接着讲了一下二次探测 上午我也是不太懂 但是没去问qwq
设
n−1=d×2r
n
−
1
=
d
×
2
r
,若n为素数,则要么
admodn=1
a
d
m
o
d
n
=
1
要么存在一个i,满足
0<=i<r
0
<=
i
<
r
且
ad×2imodn=−1
a
d
×
2
i
m
o
d
n
=
−
1
中国剩余定理
孙子那时候就会算逆元了??? (0.0) ( 0.0 )
若 m1,m2,m3...,mn m 1 , m 2 , m 3 . . . , m n 两两互质,balalba见百度百科qaq
中国剩余定理扩展
要是不互质呢?
老师讲太快了没来及写qaq
联立一下
x=a1+k1m1 x = a 1 + k 1 m 1
x=a2+k2m2 x = a 2 + k 2 m 2
k1m1−k2m2=a2−a1 k 1 m 1 − k 2 m 2 = a 2 − a 1
k1=m2gt+k′1
k
1
=
m
2
g
t
+
k
1
′
k2=m1gt+k′2
k
2
=
m
1
g
t
+
k
2
′
k′1,2 k 1 , 2 ′ 为特解
什么玩意啊qwq没怎么听懂回去看dalao笔记吧
莫比乌斯反演
我到这里估计就要懵逼了qaq
引入:整除分块//莫比乌斯反演里很重要的东西
求
for (int i=1;j;i<=n;i=j+1){
j=(n/(n/i));
ans+=(j-i+1)*(n/i);
}
老师说他也是背代码的
还有各种HenTai版本
求
怎么算的等拿到课件补一下吧qwq
莫比乌斯函数
部分内容转自巨佬的博客
十分感激这位不相识的巨佬
不是很难的东西吧,但是是反演里很重要的东西qwq
当 d=∏ki=1pi d = ∏ i = 1 k p i 且 pi p i 为互异素数时, μ(d)=(−1)k μ ( d ) = ( − 1 ) k
讲白了是将 d d 质因数分解后,每个质因子没有超过(或包含)2次幂,则就取决于 k k
其他情况
∑d|nμ(d)=[n=1] ∑ d | n μ ( d ) = [ n = 1 ]
反演
例题什么的以后做题写新博客吧QWQ
欧拉函数
φ可以预处理,φ(i)表示
在
1..i−1
1..
i
−
1
的整数中,与i互质的数的个数
可以线性筛来做
vis[1]=1;
for (int i=2;i<=n;i++){
if (!vis[i]) pri[++cnt]=i,phi[i]=i-1;
for (int j=1;j<=cnt;j++){
if (i*pri[j]>n) break;
vis[i*pri[j]]=1;
if (i % pri[j]==0) {
phi[i*pri[j]]=phi[i]*pri[j]
break;
}else phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
φ(n)是积性函数,但不是完全积性函数
一个有趣的结论
欧拉定理
设n为正整数,a时与n互质的整数
则
后面还有一些吧 不过懵逼钨丝繁衍太难了不想更了QWQ
DAY3
太难了不敢写qwq
Day4
今天是巨佬zhx来讲课
7:50来到机房,很多人跟我一样抬头膜老师一套行(ling) 云 (ren) 流(zhi) 水(xi)·的操作,似乎是在VC下打开GDB(反正我只会linuxQAQ)
闲扯
“大家会矩阵吗”
“不会”
“emm,只要你知道‘矩阵这个名字,那就是会’”
“好 那大家基础蛮好的,我们直接跳过定义”
排列和逆序对
排列,逆序对,对换,奇(偶)排列的定义
一些定理
- 对换改变排列的奇偶性
- 在全部 n n 阶排列中,奇偶排列各占一半
- 任意一个排列可经过一系列变换成自然排列 (1,2..N−1,N) ( 1 , 2.. N − 1 , N ) ,并且所作对换次数的奇偶性与这个排列的奇偶性相同
行列式
我觉得老师讲的行列式不清真啊qwq
因为蠢cyw的线代书不是这么说的qwq
为什么展开方式要用排列qwq
行列式基本性质(初等变换)
(不写了反正我会2333333)
解方程
初等变换
- 交换两个方程
- 一个方程乘k倍加到另一行
- 方程乘k倍
3个变换都是将方程组变为同解方程组
系数矩阵&增广矩阵
高斯消元
#include<bits/stdc++.h>
#define maxn 1010
using namespace std;
int n;
double a[maxn][maxn];
double b[maxn];
const double eps=1e-8;
int sign(double x){//判断正负
if (fabs(x)<=eps) return 0;
if (x>0) return 1;
return -1;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
for (int i=1;i<=n;i++) scanf("%d",&b[i]);
for (int i=1;i<=n;i++)
a[i][n+1]=b[i];
int find=0;
for (int i=1;i<=n;i++){
for (int j=i;j<=n;j++)
if (sign(a[j][i])!=0){
for (int k=1;k<=n+1;k++) swap(a[i][k],a[j][k]);
find=1;
break;
}
if (!find) gg();//无解或无数组解
for (int j=i+1;j<=n;j++){
double ratio=a[j][i]/a[i][i];
for (int k=1;k<=n+1;k++)
a[j][k]=a[j][k]-ratio*a[i][k];
}
}
}
但是这么写是非常不优美的,因为在
for (int j=i+1;j<=n;j++){
double ratio=a[j][i]/a[i][i];
for (int k=1;k<=n+1;k++)
a[j][k]=a[j][k]-ratio*a[i][k];
}
C++ C + + 这辣鸡语言可能会出现精度误差,因为可能 a[i][j] a [ i ] [ j ] 过小
所以我们引入
主元高斯消元
即在找“对角线非0元所在行”
for (int i=1;i<=n;i++){
for (int j=i;j<=n;j++)
if (sign(a[j][i])!=0){
for (int k=1;k<=n+1;k++) swap(a[i][k],a[j][k]);
find=1;
break;
}
的时候,讲a[j][i]找绝对值最大的,这样就比较优美了。
改进版
for (int i=1;i<=n;i++)
{
int p=i;
for (int j=i;j<=n;j++)
if (fabs(a[j][i]) > fabs(a[p][i])) p=j;
for (int j=1;j<=n+1;j++)
swap(a[p][j],a[i][j]);
if (sign(a[i][i]) == 0) gg();
for (int j=i+1;j<=n;j++)
{
double ratio = a[j][i] / a[i][i];
for (int k=1;k<=n+1;k++)
a[j][k] = a[j][k] - ratio*a[i][k];
}
}
矩阵
- 零矩阵
- 对角矩阵
- 单位矩阵 I I
- 纯量矩阵(对角矩阵中,对角线元素相等)
- 上三角矩阵(对角线下方为0)
- 下三角矩阵(对角线上方为0)
- 对称矩阵(关于对角线对称)
- 反对称矩阵(对称矩阵中,对称数互为相反数)
反对称矩阵,对角线必为0
相等
对应位置元素全部相等
加法
对应位置元素相加
条件:两个矩阵必须相同大小(规模)
减法类似
数乘
一个数乘矩阵,等于矩阵每个位置乘这个数
乘法
设
C=A×B
C
=
A
×
B
那么
一些性质
A0=0A=0
A
0
=
0
A
=
0
AI=IA=A
A
I
=
I
A
=
A
A(BC)=AB(C)
A
(
B
C
)
=
A
B
(
C
)
A(B+C)=AB+AC
A
(
B
+
C
)
=
A
B
+
A
C
(B+C)A=BA+CA
(
B
+
C
)
A
=
B
A
+
C
A
没有交换律
逆矩阵
设
A
A
是阶方阵,若存在
N
N
阶方阵,使得
AB=BA=I
A
B
=
B
A
=
I
,则称
A
A
是可逆的,是
A
A
的逆矩阵
否则称是不可逆的
det(A) d e t ( A )
指将矩阵当做行列式时的指
det(A)×det(B)=det(AB)
d
e
t
(
A
)
×
d
e
t
(
B
)
=
d
e
t
(
A
B
)
若
AB=I
A
B
=
I
,则有