模板

不时更新常用的模板,模板可能写的有些早,不像现在写的一样

 

数论

组合数递推公式

1 C[1][0] = C[1][1] = 1;
2 for (int i=2; i<=N; i++)
3 {
4     C[i][0] = 1;
5     for (int j=1; j<=N; j++)
6         C[i][j] = C[i-1][j]+C[i-1][j-1];
7 }
View Code

 

求逆元

a扩展欧几里得求逆元

 1 #include<cstdio>
 2 
 3 int exgcd(int a,int b,int &x,int &y)
 4 {
 5     if (b==0)
 6     {
 7         x = 1;
 8         y = 0;
 9         return a;
10     }
11     int r = exgcd(b,a%b,x,y);
12     int tmp = x;
13     x = y;
14     y = tmp-a/b*y;
15     return r;
16 }
17 
18 int main()
19 {
20     //gcd(a,p)==1
21     int a,p,r,x,y;
22     while (scanf("%d%d",&a,&p)!=EOF)
23     {
24         r = exgcd(a,p,x,y);
25         printf("%d",(x%p+p)%p);
26     }
27     return 0;
28 }
View Code

b线性求逆元

 1 int inv[MAXN]; 
 2 void INV() //线性求到a的逆元 
 3 {
 4     inv[1] = 1;
 5     for (int i=2; i<=n; ++i) {
 6         inv[i] = (1ll*(-(p/i))*inv[p%i])%p;
 7         inv[i] = (inv[i]+p)%p;
 8     }
 9 }
10 
11 /*-----------------------------------------------*/
12 
13 int INV(int a)//线性求a的逆元,可以记忆化 
14 {
15     if (a==1) return 1;
16     return ((-(p/a)*INV(p%a))%p);
17 }
View Code

c线性求阶乘的逆元 

/*
假设知道了模p下a阶乘的逆元b,fac[a] * b ≡ 1 (mod p)
那么a-1的阶乘的逆元就是,fac[a-1] * a * b ≡ 1 (mod p)
所以 b * a 就是a-1的阶乘的逆元。
*/
ifac[1000000] = ksm(1000000, mod - 2);
for (int i=1000000; i>=1; --i) ifac[i - 1] = ifac[i] * i % mod;
View Code 

 

中国剩余定理51nod1079

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline LL read() {
 6     LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9 
10 
11 LL a[100], m[100];
12 
13 LL inv(LL a,LL b,LL p) {
14     LL res = 1;
15     while (b) {
16         if (b & 1) res = res * a % p;
17         a = a * a % p;
18         b >>= 1;
19     }
20     return res;
21 }
22 
23 int main() {
24     
25     int n;scanf("%d",&n);
26     LL M = 1;
27     
28     for (int i=1; i<=n; ++i) {
29         m[i] = read();
30         a[i] = read();
31         M = M * m[i];
32     }
33 
34         
35     LL Ans = 0;
36     for (int i=1; i<=n; ++i) {
37         LL Mi = M / m[i];
38         LL T = inv(Mi,m[i]-2,m[i]);
39         Ans = (Ans + a[i] * T * Mi) % M;
40     }
41     cout << (Ans % M + M) % M;
42     return 0;
43 }
View Code

 

扩展中国剩余定理POJ2891

 1 #include<cstdio>
 2 #include<cctype>
 3 using namespace std;
 4 typedef long long LL;
 5 
 6 inline int read() {
 7     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 8     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 9 }
10 
11 LL gcd(LL a, LL b) {
12     return b == 0 ? a : gcd(b, a%b);
13 }
14 
15 void exgcd(LL a,LL b,LL &x,LL &y) {
16     if (b == 0) {
17         x = 1,b = 0;
18         return ;
19     }
20     exgcd(b,a%b,x,y);
21     LL t = x;
22     x = y;
23     y = t - a / b * y;
24 }
25 
26 LL inv(LL a,LL b) {
27     LL x = 0,y = 0;
28     exgcd(a,b,x,y);
29     x = (x % b + b) % b;
30     while (x <= 0) x += b;
31     return x;
32 }
33 
34 LL m[1010],a[1010];
35 
36 int main() {
37     int n;
38     while (scanf("%d",&n) != EOF) {
39         bool flag = true;
40         for (int i=1; i<=n; ++i) {
41             scanf("%lld%lld",&m[i],&a[i]);
42         }
43         LL m1,m2,a1,a2,c,d;
44         for (int i=2; i<=n; ++i) {
45             m1 = m[i-1], m2 = m[i], a1 = a[i-1], a2 = a[i], c = a2 - a1;
46             d = gcd(m1, m2);
47             if (c % d) {flag = false;break;}
48             m[i] = m1 * m2 / d;
49             a[i] = inv(m1/d, m2/d) * (c / d) % (m2 / d) * m1 + a1;
50             a[i] = (a[i] % m[i] + m[i]) % m[i];
51         }
52         if (!flag) puts("-1");
53         else printf("%lld\n",a[n]);
54     }
55     return 0;
56 }
View Code

 

矩阵乘法求斐波那契,矩阵快速幂(第一项是1,第二项是1)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 const int mod = 1e9+7;
 8 const int N = 2;
 9 
10 struct Matrix{
11     int a[N][N];
12     Matrix(){
13         this->clear();
14     }
15     void clear(){
16         memset(a,0,sizeof(a));
17     }
18     void setone(){
19         this->clear();
20         for (int i=0; i<N; ++i)
21             a[i][i] = 1;
22     }
23     Matrix operator * (const Matrix &x) const 
24     {
25         Matrix c;
26         for (int k=0; k<N; k++)
27             for (int i=0; i<N; ++i)
28                 for (int j=0; j<N; ++j)
29                     c.a[i][j] = (c.a[i][j]+1ll*a[i][k]*x.a[k][j])%mod;
30         return c;
31     }
32 };
33 
34 int fibn(int n)
35 {
36     Matrix x,s;
37     x.a[0][0] = x.a[0][1] = x.a[1][0] = 1;
38     s.setone();
39     for (; n; n>>=1)
40     {
41         if (n&1) s = s*x;
42         x = x*x; 
43     }
44     return (s.a[0][0]+s.a[0][1])%mod;
45 }
46 int main()
47 {
48     int n;
49     while (~scanf("%d",&n))
50     {
51         if (n==1||n==2) puts("1");
52         else printf("%d\n",fibn(n-2));
53     }
54     return 0;
55 }
重载运算符
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 const int mod = 1e9+7;
 7 const int N = 2;
 8 
 9 struct Matrix{
10     int a[N][N];
11     Matrix () {memset(a,0,sizeof(a));}
12 }t;
13 Matrix mul(Matrix a,Matrix b) {
14     Matrix c;
15     for (int k=0; k<N; k++)
16         for (int i=0; i<N; ++i)
17             for (int j=0; j<N; ++j)
18                 c.a[i][j] = (c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%mod;
19     return c;
20 }
21 int fibn(int n) {
22     Matrix x,s;
23     x.a[0][0] = x.a[0][1] = x.a[1][0] = 1;
24     s.a[0][0] = s.a[1][1] = 1;
25     while (n) {
26         if (n&1) s = mul(s,x);
27         x = mul(x,x); 
28         n >>= 1;
29     }
30     return (s.a[0][0]+s.a[0][1])%mod;
31 }
32 int main() {
33     int n;
34     while (~scanf("%d",&n)) {
35         if (n==1||n==2) puts("1");
36         else printf("%d\n",fibn(n-2));
37     }
38     return 0;
39 }
函数版

 

线性筛素数O(n)

1 for (int i=2; i<=N; i++) {
2     if (!noprime[i]) {
3         prime[++tot]=i;
4     }
5     for (int j=1; j<=tot&&i*prime[j]<=N; j++) {
6         noprime[i*prime[j]] = true;
7         if(i % prime[j] == 0) break ;  
8     }
9 }
View Code

 

线性筛欧拉函数

 1 for (int i=2; i<=N; i++) {
 2     if (!noprime[i]) {
 3         prime[++tot]=i;
 4         phi[i] = i-1; 
 5     }
 6     for (int j=1; j<=tot&&i*prime[j]<=N; j++) {
 7         noprime[i*prime[j]] = true;
 8         if(i % prime[j] == 0) {
 9             phi[i * prime[j]] = phi[i] * prime[j];
10             break ; //重要 
11         }
12         else phi[i * prime[j]] = phi[i]*(prime[j]-1);
13     }
14 }
View Code

 

线性筛莫比乌斯函数

 1 void getmu() {
 2     mu[1] = 1;
 3     for (int i=2; i<=N; ++i) {
 4         if (!noprime[i]) prime[++tot] = i,mu[i] = -1;
 5         for (int j=1; j<=tot&&i*prime[j]<=N; ++j) {
 6             noprime[i * prime[j]] = true;
 7             if (i % prime[j] == 0) {mu[i * prime[j]] = 0; break;}
 8             mu[i * prime[j]] = - mu[i];
 9         }
10     }
11 }
View Code

 

求组合数(很大!)

一般的逆元求解

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000000;
 4 const int mod=1000000007;
 5 
 6 int f[maxn+10];
 7 void init(){//阶乘
 8     f[0]=1;
 9     for(int i=1;i<=maxn;i++){
10         f[i]=1ll*f[i-1]*i%mod;
11     }
12 }
13 
14 int fast(int a,int n){
15     if (n==0) return 1;
16     if (n%2) return 1ll*a*fast(a,n-1)%mod;
17     int tmp=fast(a,n/2);
18     return 1ll*tmp*tmp%mod;
19 }
20 
21 int C(int n,int m){
22     if(n==m||m==0)return 1;
23     return (1ll*f[n]*fast(f[m],mod-2)%mod)*fast(f[n-m],mod-2)%mod;
24 }
25 
26 int main(){
27     init();
28     int n,m,k;
29     scanf("%d%d%d",&n,&m,&k);
30     int x = n-k,y = m-1;
31         printf("%d\n",C(x,y));
32     return 0;
33 }
View Code

Lucas定理

 1 //适用于p很小,n,m很大 或者 n,m不大但大于p
 2 #include<cstdio>
 3 
 4 typedef long long LL;
 5 const int N = 1000010;
 6 
 7 LL n,m,p,f[N];
 8 
 9 void init(int x) {
10     f[0] = 1;
11     for (int i=1; i<=x; ++i) f[i] = (i * f[i-1]) % x;
12 }
13 LL ksm(LL a,LL b) {
14     LL ans = 1;
15     while (b) {
16         if (b & 1) ans = (ans * a) % p;
17         b >>= 1;
18         a = (a * a) % p;
19     }
20     return ans;
21 }
22 LL C(LL n,LL m) {
23     if (m > n) return 0;
24     return (f[n] * ksm(f[m],p-2)) % p * ksm(f[n-m],p-2) % p;
25 }
26 LL Lucas(LL n,LL m) {
27     if (m == 0) return 1;
28     else return (C(n%p,m%p) * Lucas(n/p,m/p)) % p;
29 }
30 int main() {
31     int T;
32     scanf("%d",&T);
33     while (T--) {
34         scanf("%lld%lld%lld",&n,&m,&p);
35         init(p);
36         printf("%lld\n",Lucas(n,m));
37     }
38     return 0;
39 }
View Code

 

快速幂

1 int ksm(int a,int b,int p) {
2     int ret = 1;
3     while (b) {
4         if (b & 1) ret = (1ll*ret*a) % p;
5         a = (1ll*a*a)%p;
6         b >>= 1;
7     }
8     return ret%p;
9 }
View Code

 

快速乘

1 int ksc(int a,int b,int p) {
2     int ret = 0;
3     while (b) {
4         if (b & 1) ret = (ret+a)%p;
5         a = (a+a)%p;
6         b >>= 1;
7     }
8     return ret;
9 }
View Code

 

素数判定Miller_Rabin

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<ctime>
 5 
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 
10 LL ksm(LL a,LL b,LL p) {
11     LL ans = 1;
12     a = a % p;
13     while (b) {
14         if (b & 1) ans = (ans * a) % p;
15         a = (a * a) % p;
16         b >>= 1;
17     }
18     return ans;
19 }
20 bool witness(LL a,LL n,LL d,LL r) {
21     LL ret = ksm(a,d,n);
22     LL last = ret;
23     while (r--) {
24         ret = ret * ret % n;
25         if (ret==1 && last!=1 && last!=n-1) return false;
26         last = ret;
27     }
28     if (ret != 1) return false;
29     return true;
30 }
31 bool miller_rabin(LL n) {
32     if (n==2) return true;
33     if (n==1 || (n&1)==0) return false;
34     LL d = n - 1,r = 0;
35     while ((d&1)==0) r++,d>>=1;
36     for (LL i=1; i<=20; ++i) {
37         LL a = rand()%(n-1)+1;
38         if (!witness(a,n,d,r)) return false;
39     }
40     return true;
41 }
42 int main () {
43     srand((unsigned)time(NULL));
44     LL a,b;
45     while (cin >> a) {
46         if (miller_rabin(a)) cout << "yes\n";
47         else cout << "no\n";    
48     }
49     return 0;
50 }
View Code

 

 

 

FFT

递归

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 
 7 using namespace std;
 8 const int N = 300100;
 9 const double eps = 1e-8;
10 const double pi = acos(-1.0);
11 typedef long long LL;
12 
13 struct Complex {
14     double x,y;
15     Complex() {x=0,y=0;}
16     Complex(double xx,double yy) {x=xx,y=yy;}
17 
18 }A[N],B[N];
19 
20 Complex operator + (Complex a,Complex b) {
21     return Complex(a.x+b.x,a.y+b.y);
22 }
23 Complex operator - (Complex a,Complex b) { 
24     return Complex(a.x-b.x,a.y-b.y);
25 }
26 Complex operator * (Complex a,Complex b) {
27     return Complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);
28 }
29 
30 void FFT(Complex *a,int n,int ty) {
31     if (n==1) return ;
32     Complex a1[n>>1],a2[n>>1];
33     for (int i=0; i<=n; i+=2) {
34         a1[i>>1] = a[i],a2[i>>1] = a[i+1];
35     }
36     FFT(a1,n>>1,ty);
37     FFT(a2,n>>1,ty);
38     Complex w1 = Complex(cos(2.0*pi/n),ty*sin(2.0*pi/n));
39     Complex w = Complex(1.0,0.0);
40     for (int i=0; i<(n>>1); i++) {
41         Complex t = w * a2[i];
42         a[i+(n>>1)] = a1[i] - t;
43         a[i] = a1[i] + t;
44         w = w * w1;
45     }
46 }
47 int main() {
48     int n,m;
49     scanf("%d%d",&n,&m);
50     for (int i=0; i<=n; ++i) scanf("%lf",&A[i].x);
51     for (int i=0; i<=m; ++i) scanf("%lf",&B[i].x);
52     int fn = 1;
53     while (fn <= n+m) fn <<= 1;
54     FFT(A,fn,1);
55     FFT(B,fn,1);
56     for (int i=0; i<=fn; ++i) 
57         A[i] = A[i] * B[i];
58     FFT(A,fn,-1);
59     for (int i=0; i<=n+m; ++i) 
60         printf("%d ",(int)(A[i].x/fn+0.5));
61     return 0;
62 }
View Code

非递归

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 
 7 using namespace std;
 8 const int N = 300100;
 9 const double eps = 1e-8;
10 const double pi = acos(-1.0);
11 typedef long long LL;
12 
13 struct Complex {
14     double x,y;
15     Complex() {x=0,y=0;}
16     Complex(double xx,double yy) {x=xx,y=yy;}
17 
18 }A[N],B[N];
19 
20 Complex operator + (Complex a,Complex b) {
21     return Complex(a.x+b.x,a.y+b.y);
22 }
23 Complex operator - (Complex a,Complex b) { 
24     return Complex(a.x-b.x,a.y-b.y);
25 }
26 Complex operator * (Complex a,Complex b) {
27     return Complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);
28 }
29 void FFT(Complex a[],int n,int ty) {
30     for (int i=0,j=0; i<n; ++i) {
31         if (i < j) swap(a[i],a[j]);
32         for (int k=n>>1; (j^=k)<k; k>>=1);//-----
33     }
34     for (int s=1; (1<<s)<=n; ++s) {
35         int m = (1 << s);
36         Complex w1 = Complex(cos(2*pi/m),ty*sin(2*pi/m));
37         for (int i=0; i<n; i+=m) {
38             Complex w = Complex(1,0);
39             for (int k=0; k<(m>>1); ++k) {
40                 Complex t = w*a[i+k+(m>>1)];
41                 a[i+k+(m>>1)] = a[i+k] - t;//-----
42                 a[i+k] = a[i+k] + t; //-----
43                 w = w*w1;
44             }
45         }
46     }
47 }
48 int main() {
49     int n,m;
50     scanf("%d%d",&n,&m);
51     for (int i=0; i<=n; ++i) scanf("%lf",&A[i].x);
52     for (int i=0; i<=m; ++i) scanf("%lf",&B[i].x);
53     int fn = 1;
54     while (fn <= n+m) fn <<= 1;
55     FFT(A,fn,1);
56     FFT(B,fn,1);
57     for (int i=0; i<=fn; ++i) 
58         A[i] = A[i] * B[i];
59     FFT(A,fn,-1);
60     for (int i=0; i<=n+m; ++i) 
61         printf("%d ",(int)(A[i].x/fn+0.5));
62     return 0;
63 }
View Code

 

图论

树上倍增lca模板(例题https://www.luogu.org/problem/show?pid=3379

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 const int N = 1000100;
 7 
 8 struct Edge{
 9     int v,nxt;
10 }e[N];
11 int fa[N][25];    //开25,一开始开的20,找了好长时间的错误 
12 int deth[N];    
13 int head[N];
14 int n,m,s,cnt,a,b,d;
15 
16 void add(int u,int v)
17 {
18     cnt++;
19     e[cnt].v = v;
20     e[cnt].nxt = head[u];
21 //    e[cnt]=(Edge) {v,head[u]};    
22     head[u] = cnt;
23 }
24 
25 void dfs(int x)
26 {
27     for (int i=head[x]; i; i=e[i].nxt)
28     {
29         int v = e[i].v;
30         if(!deth[v])//判重,因为扫过的点都有了深度,也可以另设一个v数组 
31         {
32             deth[v] = deth[x]+1;
33             fa[v][0] = x;
34             dfs(v);
35         }
36     }
37 }
38 
39 void init()
40 {
41     for (int j=1; j<=20; ++j)
42         for (int i=1; i<=n; ++i)
43             fa[i][j] = fa[fa[i][j-1]][j-1];
44 }
45 
46 int lca(int u,int v)
47 {
48     if (deth[u] < deth[v]) swap(u,v);
49     /*for (int i=20; i>=0; --i)    
50     {
51         if (deth[fa[u][i]] >= deth[v])
52             u = fa[u][i];
53     }*/
54     d = deth[u]-deth[v];    //位运算 
55     for (int i=0; i<=20; ++i)
56     {
57         if ((1<<i) & d)
58             u = fa[u][i];
59     }
60     if (u==v) return u;
61     for (int i=20; i>=0; --i)
62     {
63         if(fa[u][i] != fa[v][i])
64         {
65             u = fa[u][i];
66             v = fa[v][i];
67         }
68     }
69     return fa[u][0];
70 }
71 
72 int main()
73 {
74     scanf("%d%d%d",&n,&m,&s);
75     for (int i=1; i<n; ++i)
76     {
77         scanf("%d%d",&a,&b);
78         add(a,b);
79         add(b,a);
80     }
81     deth[s] = 1;
82     fa[s][0] = 0;
83     dfs(s);
84     init();
85     for (int i=1; i<=m; ++i)
86     {
87         scanf("%d%d",&a,&b);
88         printf("%d\n",lca(a,b));
89     }
90     return 0;
91 }
View Code

 

求树的直径

 1 /*
 2 我们在树上任选一个节点u,以这个点为根进行一遍dfs,可以求出距离点u最远的点s,
 3 再由s为根进行一遍dfs,找到距离s最远的点t,点s与点t之间的路径即为树的直径。
 4 */
 5 
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<vector>
 9 #include<algorithm>
10 using namespace std;
11 const int MAXN = 100010;
12 int dis[MAXN];
13 vector<int>tree[MAXN];
14 
15 void dfs(int now)
16 {
17     for (int i=0; i<tree[now].size(); ++i)
18     {
19         if (!dis[tree[now][i]])
20         {
21             dis[tree[now][i]] = dis[now]+1;
22             dfs(tree[now][i]);
23         }
24     }
25 }
26 
27 int main()
28 {
29     int n,t,ans;
30     scanf("%d",&n);
31     for (int u,v,i=1; i<n; ++i)
32     {
33         scanf("%d%d",&u,&v);
34         tree[u].push_back(v);
35         tree[v].push_back(u);
36     }
37     t = 1;
38     dis[t] = 0;
39     dfs(t);
40     for (int i=1; i<=n; ++i)
41         if (dis[i]>dis[t]) t = i;
42     memset(dis,0,sizeof(dis));
43     dis[t] = 0;
44     dfs(t);
45     ans = 1;
46     for (int i=1; i<n; ++i)
47         if (dis[i]>dis[ans]) ans = i;
48     printf("%d",dis[ans]);
49     return 0;
50 }
View Code

 

最小生成树 kruskal 算法(例题https://www.luogu.org/problem/show?pid=3366

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 struct edge{
 8     int a,b,c;
 9 }e[200100];
10 int n,m;
11 int far[5100];
12 int ans,cnt;
13 
14 int find(int a)
15 {
16     return far[a]==a?a:far[a]=find(far[a]);
17 }
18 bool cmp(edge a,edge b)
19 {
20     return a.c<b.c;
21 }
22 
23 int main()
24 {
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;++i) far[i] = i;
27     for(int i=1;i<=m;++i)
28     {
29         int a,b,c;
30         scanf("%d%d%d",&a,&b,&c);
31         e[i].a=a;
32         e[i].b=b;
33         e[i].c=c;
34     }
35     sort(e+1,e+m+1,cmp);
36     for(int i=1;i<=m;++i)
37     {
38         int aa = find(e[i].a);
39         int bb = find(e[i].b);
40         if(aa!=bb)
41         {
42             cnt++;
43             far[aa] = bb;
44             ans += e[i].c;
45             if(cnt==(n-1))break;
46         }
47     }
48     if(cnt==(n-1)) cout<<ans;
49     else cout<<"orz";
50     return 0;
51 }
View Code

 

最短路 spfa 算法 (例题https://www.luogu.org/problem/show?pid=3371

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int MAXN = 10100;
 7 
 8 struct Edge{
 9     int to,w,nxt;
10 }e[500100];
11 
12 int dis[MAXN];
13 int head[MAXN];
14 bool vis[MAXN];
15 queue<int>q;
16 int n,m,s,cnt;
17 
18 void add(int u,int v,int w)    //从u到v有一条长度是w的边 
19 {
20     ++cnt;
21     e[cnt].to = v;
22     e[cnt].w = w;
23     e[cnt].nxt = head[u];
24     head[u] = cnt;
25 }
26 
27 void spfa()
28 {
29     for (int i=1; i<=n; ++i)
30         dis[i] = 2147483647;
31     dis[s] = 0;
32     q.push(s);
33     vis[s] = true;
34     while (!q.empty())
35     {
36         int u = q.front();
37         q.pop();
38         for (int i=head[u]; i; i=e[i].nxt)
39         {
40             int v = e[i].to;
41             int w = e[i].w;
42             if (dis[v]>dis[u]+w)
43             {
44                 dis[v] = dis[u]+w;
45                 if (!vis[v])
46                 {
47                     q.push(v);
48                     vis[v] = true;
49                 }
50             }
51         }
52         vis[u] = false;
53     }
54 }
55 
56 int main()
57 {
58     scanf("%d%d%d",&n,&m,&s);
59     for (int u,v,w,i=1; i<=m; ++i)
60     {
61         scanf("%d%d%d",&u,&v,&w);
62         add(u,v,w);    //有向图,如果是无向图加一行add(v,u,w); 
63     }
64     spfa();
65     for (int i=1; i<=n; ++i)
66         printf("%d ",dis[i]);
67     return 0;
68 }
View Code

 

最短路 dijkstra 算法

 1 const int  MAXN = 1010;
 2 int dis[MAXN];
 3 int pre[MAXN];
 4 int w[MAXN][MAXN];
 5 bool vis[MAXN];    // 判断是否已存入该点松弛过 
 6 int n; //
 7 
 8 void Dijkstra(int st)
 9 {
10     for (int i=1; i<=n; ++i) dis[i] = w[st][i];
11     dis[st] = 0;
12     vis[st] = true;
13     pre[st] = 0;
14     for (int i=1; i<=n-1; i++)
15     {
16         int minn = 1e8;
17         int u = 0;                    // 找出当前未使用的点j的dist[j]最小值
18         for (int j=1; j<=n; ++j)
19             if (!vis[j] && dis[j]<minn)
20             {
21                 u = j;                // u保存当前邻接点中距离最小的点的号码 
22                 minn = dis[j];
23             }
24         if (u==0) break;
25         vis[u] = true; 
26         for(int v=1; v<=n; v++)
27             if(dis[u] + w[u][v] < dis[v])    //在通过新加入的u点路径找到离v0点更短的路径  
28             {
29                 dis[v] = dis[u]+w[u][v];    //更新dist 
30                 pre[v] = u;                    //记录前驱顶点 
31             }
32     }
33 }
View Code

 

堆优化的dijkstra

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 
 5 using namespace std;
 6 
 7 const int N = 10100;
 8 const int M = 500100;
 9 
10 struct Edge{
11     int to,nxt,w;
12 }e[M]; 
13 struct Node{
14     int x,dis;
15     bool operator < (const Node &a) const {
16         return dis > a.dis;
17     }
18     Node() {}
19     Node(int a,int b) {x = a,dis = b;}
20 }now;
21 int head[N],tot,dis[N];
22 bool vis[N];
23 priority_queue<Node>q;
24 int n,m,s;
25 
26 inline int read() {
27     int x = 0,f = 1;char ch = getchar();
28     for (; ch<'0'||ch>'9'; ch = getchar())
29         if (ch=='-') f = -1;
30     for (; ch>='0'&&ch<='9'; ch = getchar())
31         x = x*10+ch-'0';
32     return x*f;
33 }
34 inline void add_edge(int u,int v,int w) {
35     e[++tot].to = v,e[tot].w = w,e[tot].nxt = head[u],head[u] = tot;
36 //    e[++tot].to = u,e[tot].w = w,e[tot].nxt = head[v],head[v] = tot;
37 }
38 void Dijkstra() {
39     for (int i=1; i<=n; ++i) dis[i] = 2147483647;
40     memset(vis,false,sizeof(vis));
41     dis[s] = 0;
42     q.push(Node(s,0));
43     while (!q.empty()) {
44         now = q.top();
45         q.pop();
46         int u = now.x;
47         if (vis[u]) continue;
48         vis[u] = true;
49         for (int i=head[u]; i; i=e[i].nxt) {
50             int v = e[i].to,w = e[i].w;
51             if (dis[v] > dis[u]+w) {
52                 dis[v] = dis[u]+w;
53                 q.push(Node(v,dis[v]));
54             }
55         }
56         
57     }
58 }
59 int main() {
60     n = read(),m = read(),s = read();
61     for (int i=1; i<=m; ++i) {
62         int u = read(),v = read(),w = read();
63         add_edge(u,v,w);
64     }
65     Dijkstra();
66     for (int i=1; i<=n; ++i) printf("%d ",dis[i]);
67     return 0;    
68 }
View Code

 

网络流dinic算法

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 
 7 const int MAXN = 100100;
 8 const int INF = 1e9;
 9 
10 struct Edge{
11     int to,c,nxt;
12     Edge(){}
13     Edge(int tt,int cc,int nn) {to = tt,c = cc,nxt = nn;}
14 }e[1000100];
15 queue<int>q;
16 
17 int head[MAXN],dis[MAXN];
18 int s,t,n,m,tot = 1;
19 
20 int read()
21 {
22     int x = 0, f = 1;char ch = getchar();
23     while (ch<'0'||ch>'9') {if (ch=='-') f = -1; ch = getchar();}
24     while (ch>='0'&&ch<='9') {x = x*10+ch-'0'; ch = getchar();}
25     return x*f;
26 }
27 bool bfs()
28 {
29     q.push(s);
30     memset(dis,-1,sizeof(dis));
31     dis[s] = 0;
32     while (!q.empty())
33     {
34         int u = q.front();
35         q.pop();
36         for (int i=head[u]; i; i=e[i].nxt)
37         {
38             int v = e[i].to;
39             if (dis[v]==-1&&e[i].c>0)
40             {
41                 dis[v] = dis[u]+1;
42                 q.push(v);
43             }
44         }
45     }
46     if (dis[t]!=-1) return true;
47     return false;
48 }
49 int dfs(int u,int low)
50 {
51     if (u==t) return low;
52     int w,used = 0;
53     for (int i=head[u]; i; i=e[i].nxt)
54     {
55         int v = e[i].to;
56         if (dis[v]==dis[u]+1&&e[i].c>0)
57         {
58             w = dfs(v,min(low-used,e[i].c));
59             e[i].c -= w;
60             e[i^1].c += w;
61             used += w;
62             if (used==low) return low;
63         }
64     }
65     if (!used) dis[u] = -1;
66     return used;
67 }
68 int dinic()
69 {
70     int ans = 0,t;
71     while (bfs())
72         ans += dfs(s,INF);
73     return ans;
74 }
75 int main()
76 {
77     n = read();m = read();s = read();t = read();
78     for (int u,v,w,i=1; i<=m; ++i)
79     {
80         u = read();v = read();w = read();
81         e[++tot] = Edge(v,w,head[u]);
82         head[u] = tot;
83         e[++tot] = Edge(u,0,head[v]);
84         head[v] = tot;    
85     }
86     printf("%d",dinic());
87     return 0;
88 }
View Code

 

KM算法 HDU2255

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 inline int read() {
 9     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
10     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
11 }
12 
13 const int INF = 1e9;
14 const int N = 305; //--
15 int match[N], mp[N][N], lx[N], ly[N], slack[N];
16 bool visx[N], visy[N];
17 int n;
18 
19 bool dfs(int u) {
20     visx[u] = true;
21     for (int v=1; v<=n; ++v) {
22         if (visy[v]) continue;
23         int t = lx[u] + ly[v] - mp[u][v];
24         if (!t) {
25             visy[v] = true;
26             if (!match[v] || dfs(match[v])) {
27                 match[v] = u;
28                 return true;
29             }
30         }
31         else slack[v] = min(slack[v], t);
32     }
33     return false;
34 }
35 void KM() {
36     memset(match, 0, sizeof(match));
37     memset(ly, 0, sizeof(ly));
38     for (int i=1; i<=n; ++i) 
39         for (int j=1; j<=n; ++j) 
40             lx[i] = max(lx[i], mp[i][j]);
41             
42     for (int x=1; x<=n; ++x) {
43         for (int i=1; i<=n; ++i) slack[i] = INF;
44         while (true) {
45             memset(visx, false, sizeof(visx));
46             memset(visy, false, sizeof(visy));
47             if (dfs(x)) break;
48             int d = INF;
49             for (int i=1; i<=n; ++i) 
50                 if (!visy[i]) d = min(d, slack[i]);
51             for (int i=1; i<=n; ++i) {
52                 if (visx[i]) lx[i] -= d;
53                 if (visy[i]) ly[i] += d;
54                 else slack[i] -= d;
55             }
56         }
57     }
58 }
59 int main() {
60     while (~scanf("%d",&n)) {
61         for (int i=1; i<=n; ++i) 
62             for (int j=1; j<=n; ++j) mp[i][j] = read();    
63         KM();
64         int ans = 0;
65         for (int i=1; i<=n; ++i) 
66             if (match[i]) ans += mp[match[i]][i];
67         printf("%d\n",ans);
68     }
69     return 0;
70 }
View Code

 

数据结构

树状数组,单点查询,区间修改(例题https://www.luogu.org/problem/show?pid=3368)需要用到差分的思想,即数列前后两个数的差。数组不需要开四倍

 1 //树状数组:区间修改,单点查询,差分 
 2 #include<cstdio>
 3 int sum[500100];
 4 int n,m,last = 0;
 5 int lowbit(int x)
 6 {
 7     return x&(-x);
 8 }
 9 void update(int x,int v)
10 {
11     while (x<=n)
12     {
13         sum[x] += v;
14         x += lowbit(x);
15     }
16 }
17 int query(int x)
18 {
19     int ans = 0;
20     while (x)
21     {
22         ans += sum[x];
23         x -= lowbit(x);
24     }
25     return ans;
26 }
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for (int a,i=1; i<=n; ++i)
31     {
32         scanf("%d",&a);
33         update(i,a-last);
34         last = a;
35     }
36     for (int x,y,z,a,i=1; i<=m; ++i)
37     {
38         scanf("%d",&a);
39         if (a==1)    //区间修改
40         {
41             scanf("%d%d%d",&x,&y,&z);
42             update(x,z);
43             update(y+1,-z); 
44         } 
45         else        //单点查询 
46         {
47             scanf("%d",&x);
48             printf("%d\n",query(x));
49         }
50     }
51     return 0;
52 }
View Code

 

树状数组,单点修改,区间查询(例题https://www.luogu.org/problem/show?pid=3374)这个不需要用差分

 1 //树状数组:区间查询,单点修改 
 2 #include<cstdio>
 3 int sum[500100];
 4 int n,m;
 5 int lowbit(int x)
 6 {
 7     return x&(-x);
 8 }
 9 void update(int x,int v)
10 {
11     while (x<=n)
12     {
13         sum[x] += v;
14         x += lowbit(x);
15     }
16 }
17 int query(int x)
18 {
19     int ans = 0;
20     while (x)
21     {
22         ans += sum[x];
23         x -= lowbit(x);
24     }
25     return ans;
26 }
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for (int a,i=1; i<=n; ++i)
31     {
32         scanf("%d",&a);
33         update(i,a);
34     }
35     for (int i=1; i<=m; ++i)
36     {
37         int x,y,z;
38         scanf("%d%d%d",&z,&x,&y);
39         if (z==1) update(x,y);    //单点修改 
40         else printf("%d\n",query(y)-query(x-1));
41     }
42     return 0;
43 }
View Code

 

树状数组,区间修改,区间查询 (http://codevs.cn/problem/1082/

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9 
10 const int N = 200010;
11 int a[N],b[N];
12 
13 struct BIT{
14     int n;LL c1[N],c2[N];
15     void update(int p,int v) {
16         for (int i=p; i<=n; i+=(i&(-i))) c1[i] += v,c2[i] += p*v;
17     }
18     LL query(int p) {
19         LL ans = 0;
20         for (int i=p; i; i-=(i&(-i))) ans += (p+1)*c1[i]-c2[i];
21         return ans;
22     }
23 }bit;
24 
25 int main() {
26     int n = read(),last = 0;
27     bit.n = n;
28     for (int i=1; i<=n; ++i) {
29         int tmp = read();
30         a[i] = tmp - last;
31         last = tmp;
32     }
33     for (int i=1; i<=n; ++i) 
34         bit.update(i,a[i]);
35         
36     int m = read();
37     while (m--) {
38         int opt = read();
39         if (opt == 1) {
40             int l = read(),r = read(),v = read();
41             bit.update(l,v);
42             if (r < n) bit.update(r+1,-v);
43         }
44         else {
45             int l = read(),r = read();
46             printf("%lld\n",bit.query(r)-bit.query(l-1));
47         }
48     }
49     return 0;
50 }
View Code

 

树链剖分

 1 void dfs1(int u,int f,int d)    //找重孩子 ,u是当前节点,f节点的父亲,d深度 
 2 {
 3     dep[u] = d;
 4     fa[u] = f;
 5     siz[u] = 1;
 6     for (int i=head[u]; i; i=e[i].nxt)
 7     {
 8         int v = e[i].to;
 9         if (v!=f)
10         {
11             dfs1(v,u,d+1);
12             siz[u] += siz[v];
13             if (siz[v]>siz[son[u]])//son[]数组,用来保存重儿子
14                 son[u] = v;
15         }
16     }
17 }
18 void dfs2(int x)    //找重链 
19 {
20     int t = 0;
21     if (!top[x]) top[x] = x;
22     for (int i=head[x]; i; i=e[i].nxt)
23         if (fa[x]!=e[i].to&&siz[t]<siz[e[i].to]) 
24             t = e[i].to;
25     if (t) top[t] = top[x], dfs2(t);
26     for (int i=head[x]; i; i=e[i].nxt)
27         if(fa[x]!=e[i].to&&t!=e[i].to) dfs2(e[i].to);
28 }
29 
30 /*
31 siz[]数组,用来保存以x为根的子树节点个数
32 top[]数组,用来保存当前节点的所在链的顶端节点
33 son[]数组,用来保存重儿子
34 dep[]数组,用来保存当前节点的深度
35 fa[]数组,用来保存当前节点的父亲
36 */
View Code

 

splay 基本的插入,删除,查询x数的排名,查询排名为x的数,求x的前驱,后继(例题http://www.lydsy.com/JudgeOnline/problem.php?id=3224

  1 #include<cstdio>
  2  
  3 const int N = 100010;
  4 int fa[N],ch[N][2],siz[N],cnt[N],data[N];
  5 int tn,Root;
  6 
  7 inline char nc() {
  8     static char buf[100000],*p1 = buf,*p2 = buf;
  9     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF :*p1++;
 10 }
 11 inline int read() {
 12     int x = 0,f = 1;char ch=nc();
 13     for (; ch<'0'||ch>'9'; ch = nc()) 
 14         if (ch == '-') f = -1;
 15     for (; ch>='0'&&ch<='9'; ch = nc()) 
 16         x = x*10+ch-'0';
 17     return x * f;
 18 }
 19 inline int son(int x) {
 20     return x == ch[fa[x]][1]; // - 
 21 }
 22 inline void pushup(int x) {
 23     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
 24 }
 25 inline void rotate(int x) {
 26     int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b];
 27     if (z) ch[z][c] = x;else Root = x;fa[x] = z; // 调整x的位置
 28     ch[x][!b] = y;fa[y] = x; // 调整y的位置
 29     ch[y][b] = a;if (a) fa[a] = y; // 给y另一个子节点
 30     pushup(y);pushup(x);
 31 }
 32 inline void splay(int x,int rt) {
 33     while (fa[x] != rt) {
 34         int y = fa[x],z = fa[y];
 35         if (z==rt) rotate(x);
 36         else {
 37             if (son(x)==son(y)) rotate(y),rotate(x);
 38             else rotate(x),rotate(x);
 39         }
 40     }
 41 }
 42 inline int getpre(int x) { //得到第一个比x小的数 
 43     int p = Root,ans;
 44     while (p) {
 45         if (x <= data[p]) p = ch[p][0];
 46         else ans = p,p = ch[p][1];
 47     }
 48     return ans;
 49 }
 50 inline int getsuc(int x) { // 得到第一个比x大的数
 51     int p = Root,ans;
 52     while (p) {
 53         if (x >= data[p]) p = ch[p][1];
 54         else ans = p,p = ch[p][0];
 55     }
 56     return ans;
 57 }
 58 inline int getk(int k) { // 得到k的排名
 59     int p = Root,ans = 0;
 60     while (true) {
 61         if (k < data[p]) p = ch[p][0];
 62         else {
 63             ans += (ch[p][0] ? siz[ch[p][0]] : 0);
 64             if (k==data[p]) {
 65                 splay(p,0);return ans+1;
 66             }
 67             ans += cnt[p];
 68             p = ch[p][1];
 69         }
 70     }
 71 }
 72 inline int getkth(int k) { // 得到第k个数
 73     int p = Root;
 74     while (true) {
 75         if (ch[p][0] && k <= siz[ch[p][0]]) p = ch[p][0];
 76         else {
 77             int tmp = (ch[p][0] ? siz[ch[p][0]] : 0) + cnt[p];
 78             if (k <= tmp) return data[p];
 79             k -= tmp; p = ch[p][1];
 80         }
 81     }
 82 }
 83 inline void Insert(int x) { // 插入
 84     if (Root==0) {
 85         ++tn; Root = tn; 
 86         ch[tn][1] = ch[tn][0] = fa[tn] = 0;
 87         siz[tn] = cnt[tn] = 1;data[tn] = x;
 88         return;
 89     }
 90     int p = Root,pa = 0;
 91     while (true) {
 92         if (x==data[p]) {
 93             cnt[p]++;pushup(p);pushup(pa);splay(p,0);break;
 94         }
 95         pa = p;
 96         p = ch[p][x > data[p]];
 97         if (p==0) {
 98             tn++;
 99             ch[tn][1] = ch[tn][0] = 0;siz[tn] = cnt[tn] = 1;
100             fa[tn] = pa;ch[pa][x > data[pa]] = tn;data[tn] = x; //-
101             pushup(pa),splay(tn,0);break;
102         }
103     }
104 }
105 inline void Clear(int x) {
106     ch[x][0] = ch[x][1] = fa[x] = siz[x] = cnt[x] = data[x] = 0;
107 }
108 inline void Delete(int x) { // 删除
109     getk(x);
110     if (cnt[Root] > 1) {cnt[Root]--;pushup(Root);return;}
111     if (!ch[Root][0] && !ch[Root][1]) {Clear(Root);Root = 0;return;}
112     if (!ch[Root][0]) {
113         int tmp = Root;Root = ch[Root][1];fa[Root] = 0;Clear(tmp);return;
114     }
115     else if (!ch[Root][1]) {
116         int tmp = Root;Root = ch[Root][0];fa[Root] = 0;Clear(tmp);return;
117     }
118     int tmp = Root,pre = ch[Root][0];//可以是getpre(data[Root]);等价于下面的while 
119     while (ch[pre][1]) pre = ch[pre][1];
120     splay(pre,0);
121     ch[Root][1] = ch[tmp][1];
122     fa[ch[tmp][1]] = Root;
123     Clear(tmp);
124     pushup(Root);
125 }
126 int main() {
127     int n = read();
128     while (n--){
129         int opt = read(),x = read();
130         if (opt==1) Insert(x);
131         else if (opt==2) Delete(x);
132         else if (opt==3) printf("%d\n",getk(x));
133         else if (opt==4) printf("%d\n",getkth(x));
134         else if (opt==5) printf("%d\n",data[getpre(x)]);
135         else printf("%d\n",data[getsuc(x)]);
136     }
137     return 0;
138 }
View Code

 

虚树的建立

 1 bool cmp_dfn(int a,int b) {
 2     return dfn[a] < dfn[b];
 3 }
 4 void Insert(int p) {
 5     int x = sk[top], lca = LCA(x, p);
 6     if (lca == x) { sk[++top] = p; return ; }
 7     while (lca != x) {
 8         int y = sk[--top];
 9         if (dfn[y] < dfn[lca]) {
10             add_edge(lca, x); sk[++top] = lca; 
11             break;
12         }
13         add_edge(y, x); x = y;
14     }
15     sk[++top] = p;
16 }
17 void build() {
18     int k = read();
19     for (int i=1; i<=k; ++i) A[i] = read(); 
20     sort(A + 1, A + k + 1, cmp_dfn);
21     top = 0; sk[++top] = 1;
22     if (A[1] != 1) sk[++top] = A[1];
23     else sk[++top] = A[2];
24     for (int i=(A[1]!=1?2:3); i<=k; ++i) Insert(A[i]);
25     while (--top) add_edge(sk[top], sk[top + 1]);
26 }
View Code

 

字符串

kmp模板(例题https://www.luogu.org/problem/show?pid=3375

 1 #include<cstdio>
 2 #include<cstring>
 3 
 4 char a[1000100],b[1010];
 5 int p[1010];     //最长公共前后缀长度 
 6 int s1,s2;
 7 void init()
 8 {
 9     int j = 0;
10     p[0] = 0;
11     for (int i=1; i<s2; ++i)
12     {
13         while(j>0 && b[i]!=b[j]) j = p[j-1];
14         if(b[i]==b[j]) j++;
15         p[i] = j;
16     }
17 }
18 void kmp()
19 {
20     int j = 0;
21     for (int i=0; i<s1; ++i)
22     {
23         while(j>0 && a[i]!=b[j]) j = p[j-1];
24         if(a[i]==b[j]) j++;
25         if(j==s2) printf("%d\n",i+1-s2+1); //找到匹配输出i的值,第一个字符是 0,所以加1 
26     }
27 }
28 int main()
29 {
30     scanf("%s",a);
31     scanf("%s",b);
32     s1 = strlen(a);
33     s2 = strlen(b);
34     init();
35     kmp();
36     for(int i=0;i<s2;++i)
37         printf("%d ",p[i]);
38     return 0;
39 }
View Code

 

manacher算法,求最长回文串(例题https://www.luogu.org/problem/show?pid=3805

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define MAXN 31000000
 5 using namespace std;
 6 
 7 char s[MAXN],str[MAXN];
 8 int p[MAXN],len;
 9 
10 void init()
11 {
12     len = strlen(str);
13     s[0] = '#';
14     for (int i=0; i<len; ++i)
15     {
16         s[i<<1|1] = '#';
17         s[(i+1)<<1] = str[i];
18     }
19     s[len<<1|1] = '#';
20     len = (len<<1|1);
21 }
22 int manacher()
23 {
24     int mx = 0, id;
25     for (int i=1; i<=len; ++i)
26     {
27         if (mx>i) p[i] = min(p[id<<1-1],mx-i);
28         else p[i] = 1;
29         while (s[i+p[i]]==s[i-p[i]]) p[i]++;
30         if (p[i]+i>mx) 
31             mx = p[i]+i, id = i;
32     }
33     int ans = 0;
34     for (int i=1; i<len; ++i) ans = max(ans,p[i]);
35     return ans-1;
36 }
37 int main()
38 {
39     scanf("%s",str);
40     init();
41     printf("%d",manacher());
42     return 0;
43 }
View Code

 

trie树,结构体封装函数

 1 struct Trie
 2 {
 3     int ch[MAXN][26];//MAXN=字符集*长度 
 4     int val[MAXN];
 5     int size;
 6     Trie()    //或者:函数Clear()
 7     {
 8         size = 1;
 9         memset(ch,0,sizeof(ch));
10         memset(val,0,sizeof(val));
11     }
12     int id(char c)
13     {
14         return c-'a';
15     }
16     void Insert(char* s)
17     {
18         int u = 0, len = strlen(s);
19         for (int i=0; i<len; ++i)
20         {
21             int c = id(s[i]);
22             if (!ch[u][c]) ch[u][c] = size++;
23             u = ch[u][c];
24             //如果是统计前缀单词个数,在此处上val[u]++;下面的val[u]=1删掉 
25         }
26         val[u] = 1;//标记单词是否出现过 
27     }
28     bool Find(char* s)
29     {
30         int u = 0, len = strlen(s);
31         for (int i=0; i<len; ++i)
32         {
33             int c = id(s[i]);
34             if (!ch[u][c]) return false;
35             u = ch[u][c];
36         }
37         if (val[u]) return true;//统计前缀单词个数,return val[u]; 
38         return false; 
39     }    
40 }t;
View Code

 

AC自动机模板

 1 //AC自动机 
 2 struct AC_automaton{
 3     int ch[MAXN][26],val[MAXN],last[MAXN],fail[MAXN],size,ret;
 4     void clear()
 5     { 
 6         memset(ch[0],0,sizeof(ch[0]));
 7         memset(val,0,sizeof(val));
 8         memset(fail,0,sizeof(fail));
 9         size = 0;
10         ret = 0;
11     }
12     int idx(char c)
13     {
14         return c-'a';
15     }
16     void insert(char *s)//插入一个字符串 
17     {
18         int u = 0,len = strlen(s);
19         for (int i=0; i<len; ++i)
20         {
21             int c = idx(s[i]);
22             if (!ch[u][c])
23             {
24                 ch[u][c] = ++size;
25                 val[size] = 0;
26                 memset(ch[size],0,sizeof(ch[size]));
27             }
28             u = ch[u][c];
29         }
30         val[u] ++;
31     }
32     void getfail()//处理fail指针 
33     {
34         queue<int>q;
35         fail[0] = 0;
36         for (int c=0; c<26; ++c) 
37         {
38             int u = ch[0][c];
39             if (u) 
40             {
41                 fail[u] = 0;q.push(u);last[u] = 0;
42             }
43         }
44         while (!q.empty())
45         {
46             int r = q.front();q.pop();
47             for (int c=0; c<26; ++c)
48             {
49                 int u = ch[r][c];
50                 if (!u)
51                 {
52                     ch[r][c] = ch[fail[r]][c];//有这一行就可以减去89行 
53                     continue;
54                 }
55                 q.push(u);
56                 int v = fail[r];
57                 while (v && !ch[v][c]) v = fail[v];
58                 fail[u] = ch[v][c];
59                 last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
60             }
61         }
62     }
63     void solve(int j)//可以任意改变的函数,看题目需要什么,这个是处理文本串中有多少个模式串 
64     {
65         if (!j) return ;
66         if (val[j])
67         {
68             ret += val[j];
69             val[j] = 0;
70         }
71         solve(last[j]);
72     }
73     void find(char *T)//遍历一遍文本串 
74     {
75         int j = 0,len = strlen(T);
76         for (int i=0; i<len; ++i)
77         {
78             int c = idx(T[i]);
79             //while (j && !ch[j][c]) j = fail[j];
80             j = ch[j][c];
81             if (val[j]) solve(j);
82             else if (last[j]) solve(last[j]);
83         }
84     }
85     
86 }ac;
View Code

 

后缀数组

 1 int s[N];
 2 int t1[N],t2[N],c[N],sa[N],height[N],rank[N];
 3 int n,m = 130,k;
 4 
 5 void get_sa() {
 6     int i,p,*x = t1,*y = t2;
 7     for (i=0; i<m; ++i) c[i] = 0;
 8     for (i=0; i<n; ++i) x[i] = s[i],c[x[i]]++;
 9     for (i=1; i<m; ++i) c[i] += c[i-1];
10     for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
11     for (int k=1; k<=n; k<<=1) {
12         p = 0;
13         for (i=n-k; i<n; ++i) y[p++] = i;
14         for (i=0; i<n; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
15         for (i=0; i<m; ++i) c[i] = 0;
16         for (i=0; i<n; ++i) c[ x[y[i]] ]++;
17         for (i=1; i<m; ++i) c[i] += c[i-1];
18         for (i=n-1; i>=0; --i) sa[--c[ x[y[i]] ]] = y[i];
19         swap(x,y);
20         p = 1;
21         x[sa[0]] = 0;
22         for (i=1; i<n; ++i) 
23             x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k] ? p-1:p++;
24         if (p>=n) break;
25         m = p;
26     }
27 }
28 void get_height() {
29     for (int i=0; i<n; ++i) rank[sa[i]] = i;
30     int k = 0;
31     height[0] = 0;
32     for (int i=0; i<n; ++i) {
33         if (!rank[i]) continue;
34         if (k) k--;
35         int j = sa[rank[i]-1];
36         while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++;
37         height[rank[i]] = k;
38     }
39 }
View Code

 

Hash

1 void init() {
2     mi[0] = 1;
3     for (int i=1; i<=n; ++i) mi[i] = mi[i - 1] * Base;
4     for (int i=1; i<=n; ++i) Hash[i] = Hash[i - 1] * Base + (s[i] - 'a' + 1);
5 }
6 uLL gethash(int l,int r) {
7     return Hash[r] - Hash[l] * mi[r - l + 1];
8 }
View Code

 

计算几何

Graham求凸包,luogu2742

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cctype>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long LL;
 9 
10 double read() {
11     double x = 0, f = 1, y = 0.1; char ch = getchar();
12     for (; !isdigit(ch)&&ch!='.'; ch=getchar()) if (ch=='-') f = -1;
13     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0';
14     if (ch == '.') ch = getchar();
15     for (; isdigit(ch); ch=getchar()) x += (ch - '0') * y, y *= 0.1;
16     return x * f;
17 }
18 
19 const double eps = 1e-8;
20 
21 struct Vector{
22     double x,y;
23     Vector() {}
24     Vector(double a,double b) { x = a, y = b; }
25 };
26 typedef Vector Point;
27 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
28 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
29 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
30 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
31 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
32 
33 int dcmp(double x) {
34     if (fabs(x) <= eps) return 0;
35     return x > 0 ? x : -x;
36 }
37 double cross(Vector a, Vector b) {
38     return a.x * b.y - a.y * b.x;
39 }
40 double len(Vector a) {
41     return sqrt(a.x * a.x + a.y * a.y);
42 }
43 
44 double X,Y;
45 bool cmp_angle(Point a,Point b) {
46     if (atan2(a.y-Y,a.x-X) == atan2(b.y-Y,b.x-X)) return a.x < b.x;
47     return atan2(a.y-Y,a.x-X) < atan2(b.y-Y,b.x-X);
48 }
49 
50 const int N = 100100;
51 Point A[N], sk[N];
52 int n;
53 
54 void Graham() {
55     Y = 1e9;
56     int t, Top = 0;
57     for (int i=1; i<=n; ++i) 
58         if (A[i].y < Y) Y = A[i].y, X = A[i].x, t = i;
59     swap(A[t],A[1]);
60     sort(A+2,A+n+1,cmp_angle);
61     sk[++Top] = A[1];
62     sk[++Top] = A[2];
63     for (int i=3; i<=n; ++i) {
64         // 直线Top-1 -> A[i] 如果在Top-1 -> Top的 外侧,即逆时针旋转过去的,那么Top可以弹出。 
65         while (Top > 1 && cross(sk[Top]-sk[Top-1],A[i]-sk[Top-1]) < 0) Top--;
66         sk[++Top] = A[i];
67     }
68     double ans = 0;
69     for (int i=2; i<=Top; ++i) 
70         ans += len(sk[i] - sk[i-1]);
71     ans += len(sk[1] - sk[Top]);
72     printf("%.2lf",ans);
73 }
74 
75 int main() {
76     cin >> n;
77     for (int i=1; i<=n; ++i) 
78         A[i].x = read(), A[i].y = read();
79     Graham();
80     return 0;
81 }
View Code

 

增量排序法求半平面交,poj2451

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<cctype>
  6 #include<cmath>
  7 using namespace std;
  8 typedef long long LL;
  9 
 10 double read() {
 11     double x = 0, f = 1, y = 0.1; char ch = getchar();
 12     for (; !isdigit(ch)&&ch!='.'; ch=getchar()) if (ch=='-') f = -1;
 13     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0';
 14     if (ch == '.') ch = getchar();
 15     for (; isdigit(ch); ch=getchar()) x += (ch - '0') * y, y *= 0.1;
 16     return x * f;
 17 }
 18 
 19 const double eps = 1e-8;
 20 
 21 struct Vector{
 22     double x,y;
 23     Vector() {}
 24     Vector(double a,double b) { x = a, y = b; }
 25 };
 26 typedef Vector Point;
 27 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
 28 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
 29 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
 30 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
 31 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
 32 
 33 struct Line{
 34     Point s, t;
 35     double angle;
 36     Line () {}
 37     Line (Point a,Point b) {s = a, t = b, angle = atan2(b.y - a.y, b.x - a.x);}
 38     
 39 };
 40 
 41 int dcmp(double x) {
 42     if (fabs(x) <= eps) return 0;
 43     return x > 0 ? 1 : -1;
 44 }
 45 double cross(Vector a, Vector b) {
 46     return a.x * b.y - a.y * b.x;
 47 }
 48 Point jiaodian(Line a, Line b) {
 49     Point A = a.s, B = a.t, C = b.s, D = b.t;
 50     double t1 = cross(D - A, B - A), t2 = cross(B - A, C - A);
 51     double t = t1 / (t1 + t2);
 52     return C * t + D * (1 - t);
 53 }
 54 
 55 const int N = 20010;
 56 
 57 Point A[N];
 58 Line seg[N];
 59 int q[N];
 60 int n,tot;
 61 
 62 bool cmp_angle(Line A,Line B) { // 按极角排序,小的在前,极角相等的话,左边的在前 
 63     double d = dcmp(A.angle - B.angle);
 64     if (!d) return dcmp(cross(B.s - A.s, B.t - A.s)) > 0;
 65     return d < 0;
 66 }
 67 bool judge(Line C,Line A, Line B) { // 判断AB的交点是否在C的左边 
 68     Point p = jiaodian(A, B);
 69     return dcmp(cross(C.s - p, C.t - p)) < 0; // 在C的右边返回true 
 70 }
 71 
 72 void solve() {
 73     sort(seg+1, seg+n+1, cmp_angle);
 74     int j = 1;
 75     for (int i=2; i<=n; ++i) // 将极角相同的只保留最左边的 
 76         if (dcmp(seg[i].angle - seg[j].angle) > 0) seg[++j] = seg[i];
 77     n = j;
 78     q[1] = 1, q[2] = 2;
 79     int L = 1, R = 2;
 80     for (int i=3; i<=n; ++i) {
 81         while (L < R && judge(seg[i], seg[q[R]], seg[q[R-1]])) R --; // 栈中最后两个线段的交点在这条的右边 
 82         while (L < R && judge(seg[i], seg[q[L]], seg[q[L+1]])) L ++; // 由于是凸多边形,新加入的线段可能转回来,把起点挡在右边 
 83         q[++R] = i;
 84     }
 85     while (L < R && judge(seg[q[L]], seg[q[R]], seg[q[R-1]])) R --;
 86     while (L < R && judge(seg[q[L]], seg[q[L]], seg[q[L+1]])) L ++;
 87     q[++R] = q[L];
 88     tot = 0;
 89     for (int i=L; i<R; ++i) 
 90         A[++tot] = jiaodian(seg[q[i]], seg[q[i+1]]); // 求交点 
 91 }
 92 
 93 double Area() {
 94     double ans = 0;
 95     for (int i=2; i<tot; ++i) 
 96         ans += cross(A[i]-A[1],A[i+1]-A[1]);
 97     return ans / 2.0;
 98 } 
 99 
100 int main() {    
101     while (~scanf("%d",&n)) {
102         for (int i=1; i<=n; ++i) {
103             double a1 = read(), b1 = read(), a2 = read(), b2 = read();
104             seg[i] = Line(Point(a1, b1), Point(a2, b2));
105         }
106         seg[++n] = Line(Point(0, 0), Point(10000, 0));
107         seg[++n] = Line(Point(10000, 0), Point(10000, 10000));
108         seg[++n] = Line(Point(10000, 10000), Point(0, 10000));
109         seg[++n] = Line(Point(0, 10000), Point(0, 0));
110         solve();
111         printf("%.1lf\n",Area());
112     }
113     return 0;
114 }
View Code

 

旋转卡壳,求凸包直径,poj2187

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cctype>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long LL;
 9 
10 inline int read() {
11     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f = -1;
12     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0'; return x * f;
13 }
14 
15 struct Vector{
16     int x,y;
17     Vector() {}
18     Vector(int a,int b) { x = a, y = b; }
19 };
20 typedef Vector Point;
21 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
22 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
23 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
24 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
25 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
26 
27 int len(Vector a) {
28     return a.x * a.x + a.y * a.y;
29 }
30 int cross(Vector a, Vector b) {
31     return a.x * b.y - a.y * b.x;
32 }
33 
34 const int N = 50010;
35 Point A[N], sk[N];
36 double X,Y;
37 int n, Top;
38 
39 bool cmp_angle(Point a,Point b) { // --- 
40     int t = cross(a - A[1], b - A[1]);
41     if (t > 0 || (t == 0 && len(a - A[1]) > len(b - A[1]))) return true;
42     return false;
43 }
44 
45 void Graham() {
46     int t; Top = 0; Y = 1e9;
47     for (int i=1; i<=n; ++i) 
48         if (A[i].y < Y || (A[i].y == Y && A[i].x < X)) Y = A[i].y, X = A[i].x, t = i;
49     swap(A[t], A[1]);
50     sort(A+2, A+n+1, cmp_angle);
51     sk[++Top] = A[1];
52     sk[++Top] = A[2];
53     for (int i=3; i<=n; ++i) {
54         while (Top > 1 && cross(sk[Top] - sk[Top-1], A[i] - sk[Top-1]) < 0) Top --;
55         sk[++Top] = A[i];
56     }
57 }
58 int Area(Point a,Point b,Point c) {
59     return cross(b - a, c - a);
60 }
61 void RC() {
62     sk[++Top] = sk[1];
63     int p = 2;
64     int ans = len(sk[2] - sk[1]);
65     for (int i=1; i<Top; ++i) {
66         while (Area(sk[i],sk[i+1],sk[p+1]) > Area(sk[i],sk[i+1],sk[p])) p = p % Top + 1;
67         ans = max(ans, max(len(sk[p] - sk[i]), len(sk[p] - sk[i+1])));
68     }
69     printf("%d\n",ans);
70 }
71 int main() {
72     while (~scanf("%d",&n)) {
73         for (int i=1; i<=n; ++i) 
74             A[i].x = read(), A[i].y = read();
75         Graham();
76         RC();
77     }
78     return 0;
79 }
View Code

 

其他

二分答案

a最小值最大

 1 //最小值最大
 2 int l = min_ans, r = max_ans;  
 3 while (l < r) 
 4 {  
 5     int mid = (l+r+1)/2;   //+1避免 r==l+1 时mid一直等于l,从而死循环  
 6     if (ok(mid))    //符合条件返回True  
 7         l = mid;  
 8     else  
 9         r = mid - 1;  
10 }  
View Code

 

b最大值最小

 1 //最大值最小
 2 int l = min_ans, r = max_ans;  
 3 while (l < r) 
 4 {  
 5     int mid = (l+r)/2;  
 6     if (ok(mid))    //符合条件返回True  
 7         r = mid;  
 8     else  
 9         l = mid + 1;  
10 } 
View Code

 

归并排序模板(例题https://www.luogu.org/problem/show?pid=1177

 1 #include<cstdio>
 2 
 3 int n,ans;
 4 int a[500100],b[500100];    //a原数组,b暂存数组 
 5 
 6 void merge_sort(int l,int r)    //归并 
 7 {
 8     if (l==r) return ;    //一个数不用排序 
 9     int m = (l+r)>>1;
10     merge_sort(l,m);    //排序左边 
11     merge_sort(m+1,r);    //排序右边 
12     int i = l, j = m+1, k = l ;    //i左边最小的位置,j右边最小的位置 
13     while (i<=m && j<=r)
14         if (a[i]<=a[j]) b[k++] = a[i++];
15         else b[k++] = a[j++];
16     while (i<=m) b[k++] = a[i++];    //加入左边剩余的数 
17     while (j<=r) b[k++] = a[j++];    //加入右边剩余的数
18     for (i=l; i<=r; ++i) a[i] = b[i];    //从暂存数组中赋值 
19 }
20 
21 int main()
22 {
23     scanf("%d",&n);
24     for (int i=1; i<=n; ++i)
25         scanf("%d",&a[i]);
26     merge_sort(1,n);
27     for (int i=1; i<=n; ++i)
28         printf("%d ",a[i]);
29     return 0;
30 }
View Code

 

归并排序求逆序对(例题https://www.luogu.org/problem/show?pid=1908

 1 #include<cstdio>
 2 
 3 int n,ans;
 4 int a[500100],b[500100];    //a原数组,b暂存数组 
 5 
 6 void merge_sort(int l,int r)    //归并 
 7 {
 8     if (l==r) return ;    //一个数不用排序 
 9     int m = (l+r)>>1;
10     merge_sort(l,m);    //排序左边 
11     merge_sort(m+1,r);    //排序右边 
12     int i = l, j = m+1, k = l ;    //i左边最小的位置,j右边最小的位置 
13     while (i<=m && j<=r)
14         if (a[i]<=a[j]) b[k++] = a[i++];
15         else ans += m-i+1, b[k++] = a[j++];    //加入右半段时,逆序对数增加 
16     while (i<=m) b[k++] = a[i++];    //加入左边剩余的数 
17     while (j<=r) b[k++] = a[j++];    //加入右边剩余的数
18     for (i=l; i<=r; ++i) a[i] = b[i];    //从暂存数组中赋值 
19 }
20 
21 int main()
22 {
23     scanf("%d",&n);
24     for (int i=1; i<=n; ++i)
25         scanf("%d",&a[i]);
26     merge_sort(1,n);
27     printf("%d",ans);
28     return 0;
29 }
View Code

 

树状数组求逆序对

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 
 8 using namespace std;
 9 
10 const int N = 100010;
11 
12 struct Node{
13     int val,pos;
14     bool operator < (const Node &a) const {
15         return val > a.val;
16     }
17 }a[N];
18 int sum[N],n;
19 
20 inline int read() {
21     int x = 0,f = 1;char ch=getchar();
22     for (; !isdigit(ch); ch=getchar()) if(ch=='-')f=-1;
23     for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
24     return x*f;
25 }
26 void update(int p,int x) {
27     for (; p<=n; p+=p&(-p)) sum[p] += x;
28 }
29 int query(int p) {
30     int ans = 0;
31     for (; p>=1; p-=p&(-p)) ans += sum[p];
32     return ans;
33 }
34 int main() {
35     n = read();
36     for (int i=1; i<=n; ++i) 
37         a[i].val = read(),a[i].pos = i;
38     sort(a+1,a+n+1);
39     int ans = 0;
40     for (int i=1; i<=n; ++i) {
41         ans += query(a[i].pos-1);
42         update(a[i].pos,1);
43     }
44     cout << ans;
45     return 0;
46 }
View Code

 

 二分查找一个数,必须要排好序

 1 int binary_search(int x,int y,int c)
 2 {
 3     int l,r,mid;
 4     l = x; 
 5     r = y;
 6     while (l<r)
 7     {
 8         mid = (l+r)>>1;
 9         if (c<=a[mid]) r = mid;
10         else l = mid+1;
11     }
12     return l;
13 }
14 /*------------------------------------*/
15 int find(int l,int r,int x)
16 {
17     while (l<=r)
18     {
19         int mid = (l+r)>>1;
20         if (a[mid]<=x) l = mid+1;
21         else r = mid-1;
22     }
23     return l;
24 }
二分查找

 

等价于(stl):

1 lower_bound(a+x,a+y+1,c)-a; 
lower_bound

 

 快速排序

 1 void qsort(int l,int r)
 2 {
 3     int i = l,j = r;
 4     int mid = a[(l+r)>>1];
 5     while (i<=j)
 6     {
 7         while (a[i]<mid) i++;
 8         while (a[j]>mid) j--;
 9         if (i<=j)
10         {
11             int t = a[i]; a[i] = a[j]; a[j] = t;
12             i++; j--;
13         }
14     }
15     if (i<r) qsort(i,r);
16     if (l<j) qsort(l,j);
17 }
快排

 

快速排序求第k大的数

 1 int qsort(int *a,int l,int r)
 2 {
 3     int tmp = a[l],pos = l;
 4     int i = l, j = r;
 5     while (i<j)
 6     {
 7         while (i<j&&a[j]>tmp) j--;
 8         if (i<j)
 9         {
10             a[pos] = a[j];
11             pos = j;
12         }
13         while (i<j&&a[i]<tmp) i++;
14         if (i<j)
15         {
16             a[pos] = a[i];
17             pos = i;
18         }
19     }
20     a[pos] = tmp;
21     return pos;
22 }
23 int findkth(int *a,int n,int k)
24 {
25     int l = 0,r = n-1;
26     while (1)
27     {
28         int pos = qsort(a,l,r);
29         if (pos==n-k) return a[pos];
30         else if (pos<n-k) l = pos+1;
31         else r = pos-1;
32     }
33 }
快速排序求第k大的数

 

dfs序

 1 void dfs(int u,int fa) {
 2     q[++tot] = u;
 3     L[u] = tot;
 4     for (int i=head[u]; i; i=e[i].nxt) {
 5         int v = e[i].to;
 6         if (v==fa) continue;
 7         dfs(v,u);
 8     }
 9     R[u] = tot;
10 }
View Code

 

生成下一个(前一个)排列

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4  
 5 using namespace std;
 6  
 7 int main()
 8 {
 9     string s;
10     cin>>s; // 包括string类型,vector,还有数组(指针左闭右开) 
11     sort(str.begin(), str.end());
12     cout<<str<<endl;
13     while (next_permutation(str.begin(), str.end())) { // 返回bool类型, 
14         cout << str << endl;
15     }
16     return 0;
17 }
18 // 相应的 前一个排列 pre_permutation 
View Code

 

 三分查找(求凸函数最大值的位置)

1 double search() {
2     while (r - l >= eps) {
3         lmid = (l + r) / 2.0;
4         rmid = (lmid + r) / 2.0;
5         if (f(lmid) >= f(rmid)) r = rmid;
6         else l = lmid;
7     }
8     return l;
9 }
View Code

 

集合hash,判断两个集合是否一样

 1 uLL getkey() {
 2     uLL a = (rand() << 15) | rand();
 3     uLL b = (rand() << 15) | rand();
 4     return a * b;    
 5 } 
 6 uLL init() {
 7     for (int i=1; i<=MAX_NUM; ++i) Key[i] = init(); // 数字i的key 
 8 }
 9 int gethash(int *A) {
10     uLL ans = 0;
11     for (int i=1; i<=n; ++i) ans = ans ^ Key[A[i]];
12     return ans;
13 }
View Code

 

 

 

  

 

——————————————————————

 

posted @ 2017-05-27 15:14  MJT12044  阅读(971)  评论(0编辑  收藏  举报