容斥原理,多步容斥

2023-11-02 08:28
文章标签 原理 容斥 多步

本文主要是介绍容斥原理,多步容斥,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 容斥意义法
    设计状态表示容斥的过程。比较简单的容斥题目一般可以容斥意义。
    如果我们要求方案数的话,通常情况下我们的把限制视为两个方面,一方面是总限制,一方面是对于每个物品的限制,这样设集合 S i S_i Si表示满足总限制以及对第 i i i个限制的方案构成的集合,若答案为 ∣ ⋃ n i = 1 S i ∣ \left| {\underset{i=1}{\overset{n}\bigcup}}S_i\right| i=1nSi ∣ ⋂ n i = 1 S i ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right| i=1nSi ,则可以使用容斥原理求解。
  2. 容斥符号法
    如果认为这个题是容斥,并且没什么太好的容斥想法,可以尝试容斥符号,例如把 = = = ≤ \leq ≥ \geq = = = ⊆ , ⊇ \subseteq,\supseteq ,(例如把双射容斥为子集), ⊂ \subset ⊆ \subseteq
  3. 修正法
    可以先编一个错误的答案,然后再考虑如何容斥掉多余的部分。很多较为复杂的题都可以修正。

容斥原理

一般的容斥原理就是设出集合,使得集合的并/交为答案,然后利用容斥原理求解的过程。
如果设不出集合,或者难以求解,则可以考虑更加复杂的计数方式,例如反演。

容斥原理:
补集转换 : S = U − S ‾ 补集转换:S=U-\overline{ S} 补集转换:S=US
德 ⋅ 摩根定律 : ⋃ n i = 1 S i ‾ = ⋂ n i = 1 S i ‾ , ⋂ n i = 1 S i ‾ = ⋃ n i = 1 S i ‾ 德·摩根定律:\overline{\underset{i=1}{\overset{n}{\bigcup}}S_i}=\underset{i=1}{\overset{n}{\bigcap}}\overline{S_i},\overline{\underset{i=1}{\overset{n}{\bigcap}}S_i }=\underset{i=1}{\overset{n}{\bigcup}}\overline{S_i} 摩根定律:i=1nSi=i=1nSi,i=1nSi=i=1nSi
集合的并 : ∣ ⋃ n i = 1 S i ∣ = ∑ ∅ ≠ T ⊆ [ n ] ( − 1 ) ∣ T ∣ − 1 ∣ ⋂ i ∈ T S i ∣ 集合的并:\left|\underset{i=1}{\overset{n}{\bigcup}}S_i \right|={\underset{\varnothing\not=T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|-1}\left |{\underset{i\in T}{\overset{}\bigcap}}S_i\right | 集合的并: i=1nSi ==T[n](1)T1 iTSi
集合的交 : ∣ ⋂ n i = 1 S i ∣ = ∑ T ⊆ [ n ] ( − 1 ) ∣ T ∣ ∣ ⋂ i ∈ T S i ‾ ∣ 集合的交:\left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|={\underset{T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|}\left|{\underset{i\in T}{\bigcap}\overline{S_i}}\right| 集合的交: i=1nSi =T[n](1)T iTSi

事实上求解集合的交的式子是由两步构成,根据德·摩根定律, ∣ ⋂ n i = 1 S i ∣ = U − ∣ ⋃ n i = 1 S i ‾ ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|=U-\left| {\underset{i=1}{\overset{n}\bigcup}}\overline{S_i}\right| i=1nSi =U i=1nSi
这说明集合的交=全集-补集的并,但是并集往往都比交集更难求解(除非集合之间没有交时,并集才好求解,但是我们在求解补集的并时,如果各个补集之间没有交,说明原集的并为全集,这样就不用求解了),因此我们注意到 ∣ ⋃ n i = 1 S i ‾ ∣ \left| {\underset{i=1}{\overset{n}\bigcup}}\overline{S_i}\right| i=1nSi 也是集合的交集的形式,因此我们套用容斥原理进行求解,这样的过程叫做有人称为多步容斥。

补集转化

补集转化较简单。

有标号连通图计数

n n n个节点的无向连通图有多少个,节点有标号,编号为 [ 1 , n ] [1,n] [1,n]
n < = 5000 n<=5000 n<=5000

这个题是朴素容斥,即考虑如何用容斥原理来修正答案。

f i f_i fi表示大小为 i i i的连通图数量,一个想法是首先连出一棵树,但是不太好搞,考虑补集转换,总边数为 i ( i − 1 ) 2 \frac{i(i-1)}2 2i(i1),总可能性为 h ( i ) = 2 i ( i − 1 ) 2 h(i)=2^{\frac {i(i-1)}2} h(i)=22i(i1)种,减去不连通的情况即可,那我们枚举 1 1 1号点所在的连通块大小 j j j,然后从剩下的 i − 1 i-1 i1个点中选出 j − 1 j-1 j1个点,情况数量为: f j ( i − 1 j − 1 ) f_j \begin{pmatrix}i-1\\ j-1\end{pmatrix} fj(i1j1),剩下 i − j i-j ij个点随意连边,转移方程为:
f i = h ( i ) − ∑ j < i f j ( i − 1 j − 1 ) h ( i − j ) f_i=h(i)-\underset{j<i}\sum f_j \begin{pmatrix}i-1\\ j-1\end{pmatrix}h(i-j) fi=h(i)j<ifj(i1j1)h(ij)

集合的交

容斥原理求解集合的交比较多,求解并反而比较少,因为题目往往要求同时遵守所有限制,而不是只遵守其中一个,这符合交的形式。

CF451E

限制 f i f_i fi是难以求解的,去掉 f i f_i fi的限制是好做的,很容易想到把它容斥掉。

容斥意义法:我们把选择 s s s朵花看做总限制,对第 i i i个花瓶的限制设出集合,则 S i S_i Si表示满足总共选了 s s s朵花,并且第 i i i个花瓶的花 ≤ f i \leq f_i fi的方案的集合,则答案为 ∣ ⋂ n i = 1 S i ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right| i=1nSi ,容易想到用容斥原理来求解。
则: ∣ ⋂ n i = 1 S i ∣ = ∑ T ⊆ [ n ] ( − 1 ) ∣ T ∣ ∣ ⋂ i ∈ T S i ‾ ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|={\underset{T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|}\left|{\underset{i\in T}{\bigcap}\overline{S_i}}\right| i=1nSi =T[n](1)T iTSi ,对于 T T T,我们要求出限制 i ∈ T i\in T iT均不合法的方案数,则我们指定物品 i i i至少选择了 f i + 1 f_i+1 fi+1次,剩下的次数为 s − ∑ i ∈ T ( f i + 1 ) s-\underset{i\in T}\sum (f_i+1) siT(fi+1),我们将它们划分到 n n n个花瓶中,根据集合的定义,我们不需要管这些花瓶的限制,这是隔板法问题,即 ( s − ∑ i ∈ T ( f i + 1 ) + n − 1 n − 1 ) \begin{pmatrix}s-\underset{i\in T}\sum (f_i+1)+n-1\\n-1\end{pmatrix} (siT(fi+1)+n1n1)。因此最终的式子就是: ∣ ⋂ n i = 1 S i ∣ = ∑ T ⊆ [ n ] ( − 1 ) ∣ T ∣ ( s − ∑ i ∈ T ( f i + 1 ) + n − 1 n − 1 ) \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|={\underset{T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|}\begin{pmatrix}s-\underset{i\in T}\sum (f_i+1)+n-1\\n-1\end{pmatrix} i=1nSi =T[n](1)T(siT(fi+1)+n1n1)

注:部分题解当中提到了“多重集的组合数”,很容易看成是“多重组合数”,但其实两者没啥关系。

代码(值域很大的组合数很难直接求解,我们把组合数转化为下降幂求解):

#include<iostream>
using namespace std;
const int N=20;
const long long M=1e9+7;
long long pow(long long a,long long b,long long c) {long long ans=1;while(b) {if(b&1) (ans=ans*a)%=M;(a=a*a)%=M;b>>=1;}return ans;
}
long long inv(long long x) {return pow(x,M-2,M);
}
long long a[N+5];
int n;
long long m;
long long d(long long x,long long k) {if(k==0) return 1;else return x%M*d(x-1,k-1)%M;
} 
long long calc(int s) {long long sum=0;for(int i=1;i<=n;i++) if(s>>i-1&1) sum+=a[i]+1;if(m-sum<0) return 0;return d(m-sum+n-1,n-1)*inv(d(n-1,n-1))%M;
} 
int main() {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];long long ans=0;for(int s=0;s<1<<n;s++) (ans+=calc(s)*(__builtin_popcount(s)&1?-1:1))%=M;cout<<(ans%M+M)%M;
}

P1450

容易想到把 d i d_i di容斥掉。

容斥意义:我们把购买了价值为 s s s的物品作为总限制,把对硬币 i i i的数量的限制作为集合,则设 S i S_i Si表示满足对第 i i i个硬币数量限制,且购买了价值为 s s s的物品的方案的集合,则答案为 ∣ ⋂ 4 i = 1 S i ∣ \left| {\underset{i=1}{\overset{4}\bigcap}}S_i\right| i=14Si ,接下来根据 ∣ ⋂ n i = 1 S i ∣ = ∑ T ⊆ [ n ] ( − 1 ) ∣ T ∣ ∣ ⋂ i ∈ T S i ‾ ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|={\underset{T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|}\left|{\underset{i\in T}{\bigcap}\overline{S_i}}\right| i=1nSi =T[n](1)T iTSi ,我们要求解补集的交,即对于一些硬币的限制不满足的方案数。
如果硬币 i ∈ T i\in T iT的限制不满足,显然它选了至少 d i + 1 d_i+1 di+1个,我们提前dp出 f x f_x fx表示购买了价值为 s s s物品的完全背包方案数,则此时的方案数量为 f s − ∑ i ∈ T ( d i + 1 ) f_{s-\underset{i\in T}\sum(d_i+1)} fsiT(di+1)

则本次询问的答案为: ∣ ⋂ 4 i = 1 S i ∣ = ∑ T ⊆ [ 4 ] ( − 1 ) ∣ T ∣ f s − ∑ i ∈ T ( d i + 1 ) \left| {\underset{i=1}{\overset{4}\bigcap}}S_i\right|={\underset{T\subseteq [4]}{\overset{}\sum}}(-1)^{|T|}f_{s-\underset{i\in T}\sum(d_i+1)} i=14Si =T[4](1)TfsiT(di+1)

每做一次询问,我们就进行一次容斥,复杂度为 O ( 2 4 ) O(2^4) O(24),因此总复杂度为 ( n ⋅ 2 4 ) (n\cdot 2^4) (n24)

#include<iostream>
#include<algorithm>
using namespace std;
const int R=100000;
long long f[R+5];
int a[10],b[10];
long long calc(int s,int x) {int t=1;while(s) x-=(s&1)*a[t]*(b[t]+1),s>>=1,t++;if(x<0) return 0;else return f[x];
}
int main() {int n;cin>>a[1]>>a[2]>>a[3]>>a[4]>>n;f[0]=1;for(int i=1;i<=4;i++)for(int j=a[i];j<=R;j++) f[j]+=f[j-a[i]];while(n--) {int x;cin>>b[1]>>b[2]>>b[3]>>b[4]>>x;long long ans=0;for(int i=0;i<1<<4;i++) ans+=calc(i,x)*(__builtin_popcount(i)&1?-1:1);
//		cout<<"***";cout<<ans<<endl;}
}

UVA11806

将 k 个棋子放在 n × m n\times m n×m 的棋盘上。我们将连续的紧贴棋盘边界的放置棋子位置称为边缘。问上下左右四个边缘上都至少放置一个棋子的棋子放置方案共有多少种.
可以做到 n × m ≤ 1 0 5 , k ≤ 1 0 5 n\times m\leq 10^5,k\leq 10^5 n×m105,k105

容斥意义:我们总共四个边缘,我们设 S i S_i Si表示第 i i i个边缘有棋子的所有方案构成的集合,则答案为 ∣ ⋂ S ∣ \left|\bigcap S\right| S,求解补集相当于指定一些边缘没有棋子,剩下位置随意,容斥原理求解即可。

互质问题1

给出一个整数 n n n和一个整数 m m m,求 [ 1 , m ] [1,m] [1,m]之中有多少个数与 n n n互质。
1 ≤ n , m ≤ 1 0 18 1\leq n,m\leq 10^{18} 1n,m1018

首先我们会分析出来,如果与 n n n互质,则说明这个数不含有 n n n的任何一个质因子,因此可以容斥意义:设 S i S_i Si表示 [ 1 , m ] [1,m] [1,m]中不含有 n n n的第 i i i个本质不同质因子的数的集合,则答案为 ∣ ⋂ S i ∣ |\bigcap S_i| Si,对应的 T T T相当于求出 [ 1 , m ] [1,m] [1,m]之中有多少个数含有质因子集合 T T T,则方案数为 ⌊ m ∏ i ∈ T p i ⌋ \left\lfloor\frac m{\underset{i\in T}\prod p_i}\right\rfloor iTpim

这个容斥的时间复杂度为 O ( 2 ∣ P ∣ ) O\left(2^{|P|}\right) O(2P),其中 P P P表示 n n n的本质不同质因子构成的集合,则 ∣ P ∣ = O ( ln ⁡ ln ⁡ n ) |P|=O(\ln\ln n) P=O(lnlnn)

互质问题2

给出一个整数 m m m,一个具有 n n n个元素的数组,求出 [ 1 , m ] [1,m] [1,m]中有多少个数与 n n n的所有元素互质:
n ≤ 20 , m ≤ 2 62 n\leq 20,m\leq 2^{62} n20,m262

首先会考虑到,与 n n n中所有元素互质,相当于没有 n n n中任何一个元素的任何一个质因子,因此我们可以将求出 n n n中的本质不同质因子集合,设为 P P P,则问题转化为求出 [ 1 , n ] [1,n] [1,n]当中有多少个数与 ∏ P \prod P P互质。

POJ1091

给定 n n n个数,其数值取值范围为 [ 1 , m ] [1,m] [1,m],请问有多少种情况使得这 n n n个数与 m m m的最大公约数为 1 1 1
n , m = 1 0 5 n,m=10^5 n,m=105

相当于对序列计数,满足: { a n } , a i ∈ [ 1 , m ] , gcd ⁡ ( gcd ⁡ n i = 1 { a i } , m ) = 1 \{a_n\},a_i\in[1,m],\gcd\left(\underset{i=1}{\overset n\gcd}\{a_i\},m\right)=1 {an},ai[1,m],gcd(i=1gcdn{ai},m)=1

我们会发现,如果序列的 gcd ⁡ \gcd gcd m m m不互质,说明它含有 m m m的某些质因子,则说明序列中的每个数都含有这些质因子。因此我们可以用容斥意义来做这个题:设 S i S_i Si表示 m m m的第 i i i个本质不同质因子不出现在序列最大公约数的方案的集合,则答案为 ∣ ⋂ S i ∣ |\bigcap S_i| Si,那么补集为指定 m m m的质因子集合的子集 T T T是序列每一个元素的约数,也就是说序列每一个数都是 ∏ i ∈ T p i \underset{i\in T}\prod p_i iTpi的倍数,那这样的序列共有 ⌊ m ∏ i ∈ T p i ⌋ n \left\lfloor\frac m{\underset{i\in T}\prod p_i}\right\rfloor^n iTpimn,容斥原理求解即可。

集合的并

HDU1796

题意简述:给出一个具有 n n n个元素的数组和一个整数 m m m,求出 [ 1 , m ] [1,m] [1,m]中有多少个数至少能整除 a a a数组中的一个数。
n ≤ 10 , a i , m ≤ 2 31 n\leq 10,a_i,m\leq 2^{31} n10,ai,m231

可以想到,能够整除 x x x的数的数量为 σ 0 ( x ) \sigma_0(x) σ0(x),能够整除 y y y的数量为 σ 0 ( y ) \sigma_0(y) σ0(y),还要在减去算重的数量,也就是既整除 x x x又整除 y y y的数,数量为 σ 0 ( gcd ⁡ ( x , y ) ) \sigma_0(\gcd(x,y)) σ0(gcd(x,y))
其中 σ 0 \sigma_0 σ0表示约数个数函数。

容斥意义:我们把值域为 [ 1 , m ] [1,m] [1,m]作为总限制,对“能够整除 a i a_i ai”设计集合,则 S i S_i Si表示能够整除 a i a_i ai的数的集合,答案为 ∣ ⋃ n i = 1 S i ∣ \left|\underset{i=1}{\overset{n}{\bigcup}}S_i \right| i=1nSi ,则我们根据 ∣ ⋃ n i = 1 S i ∣ = ∑ ∅ ≠ T ⊆ [ n ] ( − 1 ) ∣ T ∣ − 1 ∣ ⋂ i ∈ T S i ∣ \left|\underset{i=1}{\overset{n}{\bigcup}}S_i \right|={\underset{\varnothing\not=T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|-1}\left |{\underset{i\in T}{\overset{}\bigcap}}S_i\right | i=1nSi ==T[n](1)T1 iTSi ,只需要求解集合的交即可。
也就是对于 T T T来说,求出是所有能够整除 i ∈ T i\in T iT的数的数量,也就是 σ 0 ( gcd ⁡ i ∈ T { a i } ) \sigma_0\left({\underset{i\in T}\gcd \{a_i\}}\right) σ0(iTgcd{ai}),因此答案为 ∣ ⋃ n i = 1 S i ∣ = ∑ ∅ ≠ T ⊆ [ n ] ( − 1 ) ∣ T ∣ − 1 σ 0 ( gcd ⁡ i ∈ T { a i } ) \left|\underset{i=1}{\overset{n}{\bigcup}}S_i \right|={\underset{\varnothing\not=T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|-1}\sigma_0\left({\underset{i\in T}\gcd \{a_i\}}\right) i=1nSi ==T[n](1)T1σ0(iTgcd{ai})
约数个数函数可以通过预处理质因子等手段求出。

时间复杂度为 O ( 2 n ) O(2^n) O(2n)

P3349

这个题还可以子集反演,本质上是一样的。不过这个题完全可以直接容斥。

我们要建立一个从树节点到图节点的映射 f f f,使得 f f f为一个双射,这是不好限制的,我们把它转化为, f f f共有 n n n个不同的像。

那我们设 S i S_i Si表示第 i i i个图节点是像的方案的集合,则答案为 ∣ ⋂ n i = 1 S i ∣ = ∑ T ⊆ [ n ] ( − 1 ) ∣ T ∣ ∣ ⋂ i ∈ T S i ‾ ∣ \left| {\underset{i=1}{\overset{n}\bigcap}}S_i\right|={\underset{T\subseteq [n]}{\overset{}\sum}}(-1)^{|T|}\left|{\underset{i\in T}{\bigcap}\overline{S_i}}\right| i=1nSi =T[n](1)T iTSi ,这样 T T T相当于求解指定一些图节点不能使用,剩下的节点随便。

s = [ n ] ⊕ T s=[n]\oplus T s=[n]T,此时这个交集的大小是可以树形dp出来的,设 f u , i f_{u,i} fu,i表示dp到了树节点 u u u,节点 u u u对应图节点 i i i的方案数,则转移就是,对于 u u u的儿子 v v v对应的图节点为 j j j,只要 ( i , j ) (i,j) (i,j)在图上有连边,并且 i , j ∈ s i,j\in s i,js,就可以转移:

void dfs(int u,int fa) {for(int v=1;v<=n;v++)if(b[u][v]&&(v^fa)) {dfs(v,u);for(int i=1; i<=n; i++)if(s>>i-1&1) {long long sum=0;for(int j=1; j<=n; j++)if(s>>j-1&1)if(a[i][j])sum+=f[v][j];f[u][i]*=sum;}}
}

显然初值为 f u , i ∈ s = 1 f_{u,i\in s}=1 fu,is=1

模拟赛题

在这里插入图片描述
其中 n ≤ 20 , m ≤ 150 , k ≤ 7 , d ≤ 1 0 9 n\leq 20,m\leq 150,k\leq 7,d\leq 10^9 n20,m150,k7,d109

这个形式看起来非常的容斥,首先考虑没有 k k k的限制怎么做。这是个经典问题,设 f i , j f_{i,j} fi,j表示第 i i i秒在 j j j节点的方案数,就可以写出转移,观察到 n n n特别小, d d d特别大,因此可以矩阵快速幂加速转移。

那有了 k k k怎么做呢?首先可以子集反演,但是容斥意义还是更简单一点的。
S i S_i Si表示经过 i i i节点,到了第 d d d天的所有方案的集合,则答案为 ∣ ⋂ S i ∣ |\bigcap S_i| Si,补集相当于指定一些节点不能走,也就是禁止关于它们的转移,对于每个 T T T跑一次dp即可。
时间复杂度 O ( 2 k ⋅ n 3 ) O(2^k\cdot n^3) O(2kn3)

后记

于是皆大欢喜。

这篇关于容斥原理,多步容斥的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/329343

相关文章

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

TL-Tomcat中长连接的底层源码原理实现

长连接:浏览器告诉tomcat不要将请求关掉。  如果不是长连接,tomcat响应后会告诉浏览器把这个连接关掉。    tomcat中有一个缓冲区  如果发送大批量数据后 又不处理  那么会堆积缓冲区 后面的请求会越来越慢。

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们

Smarty模板执行原理

为了实现程序的业务逻辑和内容表现页面的分离从而提高开发速度,php 引入了模板引擎的概念,php 模板引擎里面最流行的可以说是smarty了,smarty因其功能强大而且速度快而被广大php web开发者所认可。本文将记录一下smarty模板引擎的工作执行原理,算是加深一下理解。 其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者

Restful API 原理以及实现

先说说API 再说啥是RESRFUL API之前,咱先说说啥是API吧。API大家应该都知道吧,简称接口嘛。随着现在移动互联网的火爆,手机软件,也就是APP几乎快爆棚了。几乎任何一个网站或者应用都会出一款iOS或者Android APP,相比网页版的体验,APP确实各方面性能要好很多。 那么现在问题来了。比如QQ空间网站,如果我想获取一个用户发的说说列表。 QQ空间网站里面需要这个功能。

laravel框架实现redis分布式集群原理

在app/config/database.php中配置如下: 'redis' => array('cluster' => true,'default' => array('host' => '172.21.107.247','port' => 6379,),'redis1' => array('host' => '172.21.107.248','port' => 6379,),) 其中cl