orangejuice's blog

挂了请务必叫我

Loj6061. 「2017 山东一轮集训 Day1」Sim

离线,忽略删除操作之后,为每次插入的数编号(不考虑值,仅考虑位置)。

用树状数组+链表可以确定每一个被插入的数的位置。

接下来维护序列,每一个位置有两个值: \((A_i,P_i)\) 。其中 \(A_i\) 为权值, \(P_i\) 为这一个值上次出现的位置。

由于查询操作只考虑不同的元素,即对于区间 \([l,r]\) ,我们只考虑其中 \(P_i<l\) 的部分。

如果一个位置还没有被加入序列,或者已经被删除,将其标记为 \(P_i=\infty\) 即可。用树状数组可定位 \(l,r\) 在重构序列中的位置。

此时,问题变成了单点修改,二维区间查询。

维护和,两个元素积的和,三个元素积的和即可处理操作1,操作5即数点。

动态二维数点可以通过分块或者树套树处理。

UR#23 国王

\(\sum_{i=0}^w \binom{w}{i}(t-A\cdot i)^n\)

\(\sum_{i=0}^T (X+A\cdot i)^n ()\)

\(x^n=\sum_{i=0}^n i! S(n,i) \binom{x}{i}\)

$$ F_W(x)=e{Ex}{i=0}^W (e{Ax}+e{Bx}-2)i2{W-i}) \ F_W(x)=e{Ex}2W{i=0}W (-1)^i \ F_W(x)=e{Ex}{i=0}^n (-1)^i ^W \ [x^n]F_W(x)={i=0}n [x^n]e{Ex}(-1)i ^W \ [x^n]F_W(x) [x^m]G_{T-W}(x) = \ {i=0}^n [x^n]e{Ex}(-1)i {j=0}^m [x^m]e{Fx}(-1)j \ W{T-W} \ {W=0}^T [x^n]F_W(x) [x^m]G{T-W}(x)= \ 2^T n! m!{i=0}^n [x^n]e{Ex}(-1)i {j=0}^m [x^n]e{Fx}(-1)j \ \ =2^T n! m!{i=0}^n [x^n]e{Ex}(e{Ax}+e{Bx}-2)i {j=0}^m [x^m]e{Fx}(e{Cx}+e{Dx}-2)j \ 设 f_i=x^n^i=_{j,k} (-2)^{i-j}[x^n] (e{Ax}+e{Bx})^j \ 设g_i=x^n^i \

\ $$

「300iq Contest 2」[LOJ 6719] 数仙人掌 Counting Cactus

LOJ上的 \(n\leq 18\)

如果把仙人掌上的树边看做二元环,那么可以认为仙人掌就是由很多环嵌套在一起的结构

\(n\leq 13\)

状压 \(dp\) ,300iq的题解里给出了状态,但是也只告诉了你状态。。。

\(f(i,S)\)\(i\) 号节点为根,子树集合为 \(S\) 的方案数

\(g(i,S)\)\(i\) 号节点为根,子树集合为 \(S\) 的方案数,并且强制根上只接了一个环

\(dp(u,v,S)\) 为钦定一个当前环的开头为 \(u\) ,环尾扩展到了 \(v\) ,当前包含 \(S\) 的方案数

由此得到转移为

  1. \(f(i,S)\cdot g(j,T)(S\cap T=\empty)\rightarrow f(i,S\cup T)\)

  2. \(dp(u,v,S)\cdot f(d,T)(S\cap T=\empty,(u,v)\in E) \rightarrow dp(u,d,S\cup T)\)

  3. \(dp(u,v,S) ((u,v)\in E)\rightarrow g(u,S)\)

实际上涉及到很多计算重复,因此需要在转移过程中加入一些调整:

1.在转移环时,钦定的环开头节点下方不应该接有任何其他节点

2.转移1中 \(S,T\) 合并上来时,可以保证 \(S<T\) 来避免集合加入顺序的重复

3.当环长>2时,同一个环,同一个开始位置会由于环遍历顺序的不同被转移两次

对于这个问题我的解决方法是: 让 \(\frac{dp(u,v,S)}{2}\rightarrow g(u,S)\) ,然后把环长为2的部分加上去

转移过程中涉及到集合运算都是枚举子集,因此复杂度一个很松的上限为 \(O(n^33^n)\)

转移顺序不难解决,代码比较丑

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
62
63
64
65
#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
#define Mod1(x) ((x>=P)&&(x-=P))
#define Mod2(x) ((x<0)&&(x+=P))
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)

char IO;
int rd(){
int s=0; int f=0;
while(!isdigit(IO=getchar())) if(IO=='-') f=1;
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
return f?-s:s;
}

const int N=13,M=1<<N|3,P=998244353;

int n,m;
int G[N];
int f[M][N],g[M][N];
int dp[M][N][N];

int main(){
n=rd(),m=rd();
if(n==1) return puts("1"),0;
rep(i,1,m) {
int u=rd()-1,v=rd()-1;
G[u]|=1<<v,G[v]|=1<<u;
}
int A=(1<<n)-1;
rep(i,0,n-1) g[1<<i][i]=1,dp[1<<i][i][i]=1;
rep(S,1,A) {
// dp[S][u][v]转移
rep(u,0,n-1) rep(v,0,n-1) if(S&(1<<u) && S&(1<<v)) {
int R=S^(1<<u);
if(u!=v) R^=(1<<v);
for(int T=R&(R-1);;T=(T-1)&R){
int X=T|(1<<u)|(1<<v),Y=S^X;
if(dp[X][u][v]) rep(d,0,n-1) if(f[Y][d] && G[v]&(1<<d))
dp[S][u][d]=(dp[S][u][d]+1ll*dp[X][u][v]*f[Y][d])%P;
if(!T) break;
}
}
// dp反馈给g
rep(u,0,n-1) rep(v,0,n-1) if(dp[S][u][v] && G[u]&(1<<v))
g[S][u]=(g[S][u]+1ll*(P+1)/2*dp[S][u][v])%P;
// 特判环长为2的情况
rep(i,0,n-1) rep(j,0,n-1) if(i!=j && S&(1<<i) && S&(1<<j) && G[i]&(1<<j))
g[S][i]=(g[S][i]+1ll*(P+1)/2*f[S^(1<<i)][j])%P;
// f[S][i]合并
rep(i,0,n-1) f[S][i]+=g[S][i],Mod1(f[S][i]);
rep(i,0,n-1) if(S&(1<<i)) {
int R=S^(1<<i);
for(int T=R&(R-1);T;T=(T-1)&R) {
int X=T,Y=T^R;
if(X>Y) continue;
// 防止转移顺序重复
f[S][i]=(f[S][i]+1ll*f[X|(1<<i)][i]*g[Y|(1<<i)][i])%P;
}
}
}
printf("%d\n",f[A][0]);
}

\(n\leq 18\)

前置知识:集合幂级数的 \(\ln ,\exp\)

同样上面的,一颗仙人掌可以看做若干 \(\ge 2\) 环,两两之间在某一个节点上相接构成

不妨先求出环的集合幂级数,枚举环上编号最小的点,然后走环,复杂度为 \(O(n^32^n)\) ,常数较小

接下来当然想到枚举环的交点 \(i\) ,将当前所有包含 \(i\) 的项取出,去掉 \(i\) 后求出 \(\exp\) ,然后放回去,就能计算相交在 \(i\) 上的方案

两部分复杂度均为 \(O(n^32^n)\)

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
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
enum{N=20,M=1<<18|10,P=998244353};
struct U{
int x;
U(){} U(int x):x(x){}
inline void operator += (const U &t){ x+=t.x,x>=P&&(x-=P); }
inline void operator -= (const U &t){ x-=t.x,x<0&&(x+=P); }
inline U operator * (const U &t){ return U(static_cast<unsigned long long>(x)*t.x%P); }
}I[N],F[M][N],H[M][N];
int n,m,G[N],C[M],B[M];
void FWT(int f) {
for(int i=1;i<m;i<<=1) {
for(int l=0;l<m;l+=i*2) {
for(int j=l;j<l+i;++j) {
if(f==1) rep(d,1,n) F[j+i][d]+=F[j][d];
else rep(d,1,n) F[j+i][d]-=F[j][d];
}
}
}
}
void Exp(U *a){
static U b[N];
rep(i,0,n-1) b[i]=a[i+1]*(i+1);
rep(i,0,n-1) {
U t=b[i];
rep(j,1,i) t+=a[j]*b[i-j];
a[i+1]=t*I[i+1];
}
}
int main(){
scanf("%d%d",&n,&m);
if(n==1) return puts("1"),0;
for(int x,y;m--;) scanf("%d%d",&x,&y),x--,y--,G[x]|=1<<y,G[y]|=1<<x;
I[0]=I[1]=1,m=1<<n;
rep(i,0,n-1) B[1<<i]=i;
rep(i,2,n) I[i]=U(P-P/i)*I[P%i];
rep(i,1,m-1) C[i]=C[i&(i-1)]+1;
rep(st,0,n-1) {
H[1<<st][st]=1;
rep(S,0,m-1) rep(i,st,n-1) if(H[S][i].x) {
for(int T=G[i]&~S;T;T&=T-1)
H[S|(T&-T)][B[T&-T]]+=H[S][i];
if(G[i]&(1<<st)) F[S][C[S]]+=H[S][i]*I[1+(C[S]>2)];
H[S][i]=0;
}
}
FWT(1);
for(int i=1;i<m;i<<=1){
for(int l=0;l<m;l+=i*2) for(int j=l;j<l+i;++j) {
rep(k,1,n) F[j+i][k]-=F[j][k];
Exp(F[j+i]+1);
rep(k,1,n) F[j+i][k]+=F[j][k];
}
}
FWT(-1),printf("%d\n",F[m-1][n].x);
}

\(dis_{u,s}\) 表示 在 \(\mod L=s\) 到达 \(u\) 的最小时间,其中 \(L\) 表示 \(u\) 所在环。

对于状态 \(dis_{u,s}\) ,考虑所有的边 \((u,v)\)

\(u,v\) 有一个不在环上时,转移可以分为:

  1. 如果能过去就直接过去。
  2. 等到 \(v\) 被占据之后再跟过去(跟在守卫后面)。

\((u,v)\) 为一条环边时,则只需要考虑能否直接走环边。

\(u\)\(v\) 都在环上时,可以将转移压缩为以下几种:

  1. \(t\) 表示 \(v\) 下一个被占据的时刻,如果 \(t\) 时刻 \(u\) 没有被占据,则可以采取以下方式:

    1. 通过这条边到达 \(v\)
    2. \(t\) 时刻回到 \(u\)
    3. 然后在 \(t+1\) 时刻去 \(v\)

    最后就可以跟在 \(v\) 环的守卫后面。

  2. 如果 \(t\) 时刻 \(v\) 被占据了:

    \(t'\) 表示 \(t\) 时刻以后,下一个回到 \(\mod L=s\) 的时刻,用 \(t'+1\) 更新。

    \(t''\) 表示 \(t'\) 时刻以后,下一个 \(v\) 被占据的时刻,再次检查能否用 \(1\) 中的方案。 此时由于要多留一轮,需要判断

「PA 2019」Szprotki i szczupaki

根据题意模拟,得到一种浅显的贪心方法是: 每次选择能吃的最大的一个吃掉

如果用set维护,就能得到一个 \(O(n^2\log n)\) 的算法!

考虑用加速这个贪心:

设当前重量为 \(now\) ,目标是 \(des\)

每次找到存在 \(\ge now\) 的最小的一条鱼 \(nxt\)

那么这一次决策的目标就是吃最少的鱼让自己能够吃掉 \(nxt\) 或者直接达到 \(des\)

在达到这一次的决策目标之前,能够吃的鱼的集合都是一样的

那么就可以找到最短的一段以 \(now-1\) 为右端点的区间使得区间的和达到目标

发现每做一次决策之后,下一次吃一条鱼就会翻倍,所以只有 \(\log 10^{18}\) 次决策

那么考虑如何用数据结构维护这个目标

注意一个比较难维护的问题,每次决策之后,被吃掉的鱼应当暂时消失

暂时消失的问题,常见的思路可能是:可持久化 或者 删除之后存下来回撤

平衡树

涉及到插入,删除,二分区间,删除区间和复原区间

可以用 \(\text{Splay}\) 或者非旋 \(\text{Treap}\) 维护这个问题

复原区间的过程可以写成一个伪平衡树合并的样子

非常慢

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include<bits/stdc++.h>
using namespace std;
typedef pair <int,int> Pii;
#define mp make_pair
typedef long long ll;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,const T &b){ ((a<b)&&(a=b)); }

char IO;
template <class T=int> T rd(){
T s=0; int f=0;
while(!isdigit(IO=getchar())) if(IO=='-') f=1;
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
return f?-s:s;
}

const int N=4e5+10;
const ll U=1e12;

int n,m;
int rt,c[N],ls[N],rs[N],key[N],ma[N],mi[N];
ll s[N],val[N];

int cmp(int x,int y){ return val[x]!=val[y]?val[x]<val[y]:x>y; }
void Up(int p) {
s[p]=s[ls[p]]+s[rs[p]]+val[p];
c[p]=c[ls[p]]+c[rs[p]]+1;
ma[p]=mi[p]=p;
if(ma[ls[p]] && cmp(ma[p],ma[ls[p]])) ma[p]=ma[ls[p]];
if(ma[rs[p]] && cmp(ma[p],ma[rs[p]])) ma[p]=ma[rs[p]];
if(mi[ls[p]] && cmp(mi[ls[p]],mi[p])) mi[p]=mi[ls[p]];
if(mi[ls[p]] && cmp(mi[ls[p]],mi[p])) mi[p]=mi[rs[p]];
}
void Show(int x) {
if(ls[x]) Show(ls[x]);
printf("(%d,%lld,%lld) ",x,val[x],s[x]);
if(rs[x]) Show(rs[x]);
}


int Union(int x,int y) {
if(!x || !y) return x|y;
if(key[x]<key[y]) return rs[x]=Union(rs[x],y),Up(x),x;
return ls[y]=Union(x,ls[y]),Up(y),y;
}

Pii Split(int x,int k) {
if(c[x]<=k) return mp(x,0);
if(!x || !k) return mp(0,x);
if(c[ls[x]]+1<=k) {
Pii y=Split(rs[x],k-c[ls[x]]-1);
return rs[x]=y.first,Up(x),mp(x,y.second);
} else {
Pii y=Split(ls[x],k);
return ls[x]=y.second,Up(x),mp(y.first,x);
}
}
Pii Split2(int x,int k) {
if(!x) return mp(0,0);
if(cmp(ma[x],k)) return mp(x,0);
if(cmp(k,mi[x])) return mp(0,x);
if(cmp(x,k)) {
Pii y=Split2(rs[x],k);
return rs[x]=y.first,Up(x),mp(x,y.second);
} else {
Pii y=Split2(ls[x],k);
return ls[x]=y.second,Up(x),mp(y.first,x);
}
}
Pii Split3(int x,ll k) {
if(!x) return mp(0,0);
if(s[x]<=k) return mp(0,x);
if(s[rs[x]]>=k) {
Pii y=Split3(rs[x],k);
return rs[x]=y.first,Up(x),mp(x,y.second);
} else {
Pii y=Split3(ls[x],k-s[rs[x]]-val[x]);
return ls[x]=y.second,Up(x),mp(y.first,x);
}
}

void Insert(){
val[++n]=rd<ll>(),s[n]=val[n],ma[n]=mi[n]=n,c[n]=1,key[n]=rand();
Pii t=Split2(rt,n);
rt=Union(Union(t.first,n),t.second);
}
void Erase() {
Pii x=Split2(rt,0);
Pii y=Split(x.second,1);
rt=Union(x.first,y.second);
}

int T[N],cnt;
int main(){
rep(i,1,rd()) Insert();
rep(kase,1,rd()) {
int opt=rd();
if(opt==2) Insert();
else if(opt==3) val[0]=rd<ll>()-1,Erase();
else {
ll now=rd<ll>(),des=rd<ll>(),ans=cnt=0;
while(now<des) {
val[n+1]=now;
Pii x=Split2(rt,n+1);
ll nxt=x.second?val[mi[x.second]]+1:1e18;
cmin(nxt,des);
ll d=nxt-now;
Pii y=Split3(x.first,d);
now+=s[y.second],ans+=c[y.second];
rt=Union(y.first,x.second);
T[++cnt]=y.second;
if(now<nxt) break;
}
drep(i,cnt,1) {
Pii x=Split2(rt,T[i]);
rt=Union(Union(x.first,T[i]),x.second);
}
if(now>=des) printf("%lld\n",ans);
else puts("-1");
}
}
}

线段树

离线之后写,让每个位置只包含一个数会更好写

关于用线段树维护暂时删除的问题,有很多写法

1.强行标记,把被标记的节点全部存下来然后复原

Sprinklers 2: Return of the Alfalfa P

条件是: 每个点都要被覆盖,且不能被两种覆盖,那么最后覆盖的情况一定是形如下图的

其中红色和黄色的点表示关键的覆盖点,其他点按照其所属的颜色可以选择放或者不放

那么考虑从上到下,依次对于每一层 \(dp\) 竖线的位置,那么有两种转移方法

1.保留上层竖线,两边空白位置的可行点用2的幂次乘进答案即可

2.将当前层的竖线右移,必须选择两个位置,其他位置依然按照2的幂次加入答案

直接转移是 \(O(n^3)\) 的,对于第2中转移应用前缀和优化即可做到 \(O(n^2)\)

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
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int,int> Pii;
#define reg register
#define pb push_back
#define mp make_pair
#define Mod1(x) ((x>=P)&&(x-=P))
#define Mod2(x) ((x<0)&&(x+=P))
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,const T &b){ ((a<b)&&(a=b)); }

char IO;
template <class T=int> T rd(){
T s=0; int f=0;
while(!isdigit(IO=getchar())) if(IO=='-') f=1;
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
return f?-s:s;
}

const int N=2e3+10,P=1e9+7;

int n;
char A[N][N];

int dp[N][N];
int c[N][N],rc[N][N];
int Pow[N];

int main(){
n=rd();
rep(i,1,n) scanf("%s",A[i]+1);
rep(i,1,n) rep(j,1,n) c[i][j]=c[i][j-1]+(A[i][j]=='.');
rep(i,1,n) drep(j,n,1) rc[i][j]=rc[i][j+1]+(A[i][j]=='.');
rep(i,Pow[0]=1,n) Pow[i]=Pow[i-1]*2%P;
dp[0][0]=1;
rep(i,1,n) {
int s=0;
rep(j,0,n) {
dp[i][j]=(dp[i][j]+1ll*dp[i-1][j]*Pow[c[i][j]+rc[i-1][j+1]])%P;
// 空白位置的可行点按照2的幂次加入答案
if(A[i][j]!='W') dp[i][j]=(dp[i][j]+1ll*s*(j?Pow[c[i][j]-1]:1))%P;
//把两个强制选择的关键点分开,在累入前缀和 和 从前缀和中拿出时考虑即可

if(A[i-1][j+1]!='W') s=(s+1ll*dp[i-1][j]*(i>1&&j<n?Pow[rc[i-1][j+1]-1]:1))%P;
}
}
int ans=0;
rep(i,0,n) if(A[n][i+1]!='W') ans=(ans+1ll*(i<n?Pow[rc[n][i+1]-1]:1)*dp[n][i])%P;
printf("%d\n",ans);
}

olefin

给定一个长度为 \(n\) 的01字符串

烯烃不存在连续两个碳碳双键出现的情况,因此可以把原来的序列分成若干个01交替序列,相邻之间用多个0隔开,这些序列之间不会干扰

一个包含 \(n\) 个碳碳双键的交替序列加成 \(k\) 次的方案数为 \(\displaystyle \binom{n+k}{n-k}\prod_{i=1}^{k} (2i-1)\)

证明思路:

一共有 \(\displaystyle \binom{n+k}{n-k}\) 种可能的结束状态

且任何一个合法状态均有 \(\prod_{i=1}^m (2i-1)\) 种可能的构造方法

可以从0次操作开始向上归纳,对于一个 \(k\) 次操作的状态,合法的逆操作一定是一段 两端是0的极长的 交替序列,容易通过次数分析发现此时合法的极长交替序列就只有 \(2k-1\) 个,即完成从上层的归纳

按照这个式子,分治 \(\text{NTT}\) 即可

\(\displaystyle C(x)=\sum_{i=0}^{\infty} C_i\)

易知 \(xC^2=C-1\)

\(F_{n,m}=[x^m](C-1)^n,F_n(x)=(C-1)^n\)

\(F_n(x)=(C-1)^n=xC^2 (C-1)^{n-1}=x ((C-1)^{n+1}+2(C-1)^n+(C-1)^{n-1})\)

\(F_{n,m}=F_{n+1,m-1}+2F_{n,m-1}+F_{n-1m-1}\)

\(F_{n,m}=F_{n-1,m+1}-2F_{n-1,m}-F_{n-2,m}\)

进一步规约,得到答案的表达式

\(\displaystyle Ans_i=[x^n] (C(x)-1)^i [y^i] e^{\varphi}\)

其中 \(\displaystyle \varphi=\sum _{i\ge 1}2(i+1) \cdot (C(x)-1) y^i\)

\(\displaystyle \varphi=\sum _{i\ge 1}2(i+1) \cdot (C(x)-1) y^i\)

\(\displaystyle \int \varphi\ dy =\sum_{i\ge 1} 2(C(x)-1) y^{i+1}=\sum_{i\ge 2} 2(C(x)-1) y^i\)

\(\displaystyle \int \varphi\ dy = 2(C(x)-1) \frac{y^2}{1-y}\)

\(\displaystyle \varphi=2(C(x)-1) (\frac{y^2}{1-y})'=2(C(x)-1) \frac{2y-y^2}{(1-y)^2}\)

\(G_{n,m}\)\(n\) 个白格, \(m\) 为总格数的权值

\(\displaystyle G_{n}(x)=(\sum_{i\ge 2} 2i x^i)^n\)

\(\displaystyle \varphi(x)=\sum_{i\ge 2} 2i x^i\)

\(\displaystyle \varphi(x)=2x(\sum_{i\ge 2} x^i)'=2x^2 \frac{2-x}{1-x}\)

\(G_n(x)=\varphi^n(x)\)

\(Ans_i\) 表示有 \(i\) 个白格的答案

\(Ans_i=\displaystyle \sum_j G_{i,j} F_{j,n}\)

程设笔记

主讲内容:近似算法 / 随机算法,中间会插入 oop 部分。 ## Intro

有关近似的概念

相对误差的近似:

\(\alpha\) 近似:\(output \leq \alpha \cdot ans\) 的算法

\((1+\varepsilon)\) 近似:\(output \leq (1+\varepsilon) \cdot ans\) 的算法,算法的复杂度为 \(O(f(\frac{1}{\varepsilon}))\),这里通常 \(\varepsilon \in [0.01,0.3]\)

Read more »
0%