各类模板(更新中...)(若有什么特别的需要,可以留下评论)

Posted queuelovestack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各类模板(更新中...)(若有什么特别的需要,可以留下评论)相关的知识,希望对你有一定的参考价值。

后缀数组(DC3算法,时间复杂度O(n))

#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN],wb[MAXN],wv[MAXN],ws_[MAXN];
int c0(int *r,int a,int b)

    return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];

int c12(int k,int *r,int a,int b)

    if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
    else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];

void sort(int *r,int *a,int *b,int n,int m)

    int i;
    for(i=0; i<n; i++) wv[i]=r[a[i]];
    for(i=0; i<m; i++) ws_[i]=0;
    for(i=0; i<n; i++) ws_[wv[i]]++;
    for(i=1; i<m; i++) ws_[i]+=ws_[i-1];
    for(i=n-1; i>=0; i--) b[--ws_[wv[i]]]=a[i];
    return;

void dc3(int *r,int *sa,int n,int m)

    int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
    r[n]=r[n+1]=0;
    for(i=0; i<n; i++) if(i%3!=0) wa[tbc++]=i;
    sort(r+2,wa,wb,tbc,m);
    sort(r+1,wb,wa,tbc,m);
    sort(r,wa,wb,tbc,m);
    for(p=1,rn[F(wb[0])]=0,i=1; i<tbc; i++)
        rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
    if(p<tbc) dc3(rn,san,tbc,p);
    else for(i=0; i<tbc; i++) san[rn[i]]=i;
    for(i=0; i<tbc; i++) if(san[i]<tb) wb[ta++]=san[i]*3;
    if(n%3==1) wb[ta++]=n-1;
    sort(r,wb,wa,ta,m);
    for(i=0; i<tbc; i++) wv[wb[i]=G(san[i])]=i;
    for(i=0,j=0,p=0; i<ta && j<tbc; p++)
        sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
    for(; i<ta; p++) sa[p]=wa[i++];
    for(; j<tbc; p++) sa[p]=wb[j++];

//各个参数的作用和前面的倍增算法一样,不同的地方是r数组和sa数组的
//大小都要是3*n,这为了方便下面的递归处理,不用每次都申请新的内存空间
int Rank[MAXN], height[MAXN], sa[3*MAXN], r[3*MAXN];
void calheight(int *r,int *sa,int n)

    int i,j,k=0;
    for(i=1; i<=n; i++)Rank[sa[i]]=i;
    for(i=0; i<n; height[Rank[i++]]=k)
        for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);


后缀数组(倍增算法,时间复杂度O(nlogn))

const int MAXN = 100010;
//rnk从0开始
//sa从1开始,因为最后一个字符(最小的)排在第0位
//height从1开始,因为表示的是sa[i - 1]和sa[i]
//倍增算法 O(nlogn)
int wa[MAXN], wb[MAXN], wv[MAXN], ws_[MAXN];
//Suffix函数的参数m代表字符串中字符的取值范围,是基数排序的一个参数,如果原序列都是字母可以直接取128,如果原序列本身都是整数的话,则m可以取比最大的整数大1的值
//待排序的字符串放在r数组中,从r[0]到r[n-1],长度为n
//为了方便比较大小,可以在字符串后面添加一个字符,这个字符没有在前面的字符中出现过,而且比前面的字符都要小
//同上,为了函数操作的方便,约定除r[n-1]外所有的r[i]都大于0,r[n-1]=0
//函数结束后,结果放在sa数组中,从sa[0]到sa[n-1]
void Suffix(int *r, int *sa, int n, int m)

    int i, j, k, *x = wa, *y = wb, *t;
    //对长度为1的字符串排序
    //一般来说,在字符串的题目中,r的最大值不会很大,所以这里使用了基数排序
    //如果r的最大值很大,那么把这段代码改成快速排序
    for(i = 0; i < m; ++i) ws_[i] = 0;
    for(i = 0; i < n; ++i) ws_[x[i] = r[i]]++;//统计字符的个数
    for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1];//统计不大于字符i的字符个数
    for(i = n - 1; i >= 0; --i) sa[--ws_[x[i]]] = i;//计算字符排名
    //基数排序
    //x数组保存的值相当于是rank值
    for(j = 1, k = 1; k < n; j *= 2, m = k)
    
        //j是当前字符串的长度,数组y保存的是对第二关键字排序的结果
        //第二关键字排序
        for(k = 0, i = n - j; i < n; ++i) y[k++] = i;//第二关键字为0的排在前面
        for(i = 0; i < n; ++i) if(sa[i] >= j) y[k++] = sa[i] - j;//长度为j的子串sa[i]应该是长度为2 * j的子串sa[i] - j的后缀(第二关键字),对所有的长度为2 * j的子串根据第二关键字来排序
        for(i = 0; i < n; ++i) wv[i] = x[y[i]];//提取第一关键字
        //按第一关键字排序 (原理同对长度为1的字符串排序)
        for(i = 0; i < m; ++i) ws_[i] = 0;
        for(i = 0; i < n; ++i) ws_[wv[i]]++;
        for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1];
        for(i = n - 1; i >= 0; --i) sa[--ws_[wv[i]]] = y[i];//按第一关键字,计算出了长度为2 * j的子串排名情况
        //此时数组x是长度为j的子串的排名情况,数组y仍是根据第二关键字排序后的结果
        //计算长度为2 * j的子串的排名情况,保存到数组x
        t = x;
        x = y;
        y = t;
        for(x[sa[0]] = 0, i = k = 1; i < n; ++i)
            x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j]) ? k - 1 : k++;
        //若长度为2 * j的子串sa[i]与sa[i - 1]完全相同,则他们有相同的排名
    

int Rank[MAXN], height[MAXN], sa[MAXN], r[MAXN];
void calheight(int *r,int *sa,int n)

    int i,j,k=0;
    for(i=1; i<=n; i++)Rank[sa[i]]=i;
    for(i=0; i<n; height[Rank[i++]]=k)
        for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);

int main()

    int n,i;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    
        scanf("%d",&r[i]);
        Max=max(Max,r[i]);
    
    r[i]=0;
    Suffix(r,sa,n+1,Max+1);
    calheight(r,sa,n);
    return 0;


简单多边形面积交(简单多边形面积并=简单多边形面积和-简单多边形面积交)

/*Sherlock and Watson and Adler*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 1e-9
using namespace std;
const int N = 105;
struct point

    double x,y;
    point()x = y = 0;
    point(double a, double b)
    x = a, y = b;
    inline point operator-(const point &b)const
    return point(x - b.x, y - b.y);
    inline point operator+(const point &b)const
    return point(x + b.x, y + b.y);
    inline double dot(const point &b)const
    return x * b.x + y * b.y;
    inline double cross(const point &b, const point &c)const
    return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);
a[N],b[N];
int dcmp(double x)

    if(x > eps) return 1;
    return x < -eps ? -1 : 0;

point LineCross(const point &a, const point &b, const point &c, const point &d)

    double u = a.cross(b, c), v = b.cross(a, d);
    return point((c.x * v + d.x * u) / (u + v), (c.y * v + d.y * u) / (u + v));

double PolygonArea(point p[], int n)

    if(n < 3) return 0.0;
    double s = p[0].y * (p[n - 1].x - p[1].x);
    p[n] = p[0];
    for(int i = 1; i < n; ++ i)
        s += p[i].y * (p[i - 1].x - p[i + 1].x);
    return fabs(s * 0.5);

double CPIA(point a[], point b[], int na, int nb)//ConvexPolygonIntersectArea

    point p[10], tmp[10];
    int i, j, tn, sflag, eflag;
    a[na] = a[0], b[nb] = b[0];
    memcpy(p, b, sizeof(point) * (nb + 1));
    for(i = 0; i < na && nb > 2; ++ i)
    
        sflag = dcmp(a[i].cross(a[i + 1], p[0]));
        for(j = tn = 0; j < nb; ++ j, sflag = eflag)
        
            if(sflag >= 0) tmp[tn ++] = p[j];
            eflag = dcmp(a[i].cross(a[i + 1], p[j + 1]));
            if((sflag ^ eflag) == -2)
                tmp[tn ++] = LineCross(a[i], a[i + 1], p[j], p[j + 1]);
        
        memcpy(p, tmp, sizeof(point) * tn);
        nb = tn, p[nb] = p[0];
    
    if(nb < 3) return 0.0;
    return PolygonArea(p, nb);

double SPIA(point a[], point b[], int na, int nb)//SimplePolygonIntersectArea

    int i, j;
    point t1[4], t2[4];
    double res = 0, if_clock_t1, if_clock_t2;
    a[na] = t1[0] = a[0], b[nb] = t2[0] = b[0];
    for(i = 2; i < na; ++ i)
    
        t1[1] = a[i - 1], t1[2] = a[i];
        if_clock_t1 = dcmp(t1[0].cross(t1[1], t1[2]));
        if(if_clock_t1 < 0) std::swap(t1[1], t1[2]);
        for(j = 2; j < nb; ++ j)
        
            t2[1] = b[j - 1], t2[2] = b[j];
            if_clock_t2 = dcmp(t2[0].cross(t2[1], t2[2]));
            if(if_clock_t2 < 0) std::swap(t2[1], t2[2]);
            res += CPIA(t1, t2, 3, 3) * if_clock_t1 * if_clock_t2;
        
    
    return res;

int main()

    int n,m,i,p=1;
    while(~scanf("%d",&n))
    
        for(i=0;i<n;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        scanf("%d",&m);
        for(i=0;i<m;i++)
            scanf("%lf%lf",&b[i].x,&b[i].y);
        printf("%.8f\\n",fabs(SPIA(a,b,n,m)));
    
    return 0;


中国剩余定理模板(求解一元模线性方程组)

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-8
#define LL long long
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 105;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
int group;
LL n[N],a[N];
LL Egcd(LL a,LL b,LL &x,LL &y)

    if(b==0)
    
        x=1,y=0;
        return a;
    
    LL d,tp;
    d=Egcd(b,a%b,x,y);
    tp=x;
    x=y;
    y=tp-a/b*y;
    return d;

LL solve()

    int i;
    bool flag = false;
    LL n1 = n[0], n2, b1 = a[0], b2, bb, d, t, k, x, y;
    for (i = 1; i < group; i++)
    
        n2 = n[i], b2 = a[i];
        bb = b2 - b1;
        d = Egcd (n1, n2, x, y);
        if (bb % d)     //模线性解k1时发现无解
        
            flag = true;
            break;
        
        k = bb / d * x;    //相当于求上面所说的k1【模线性方程】
        t = n2 / d;
        if (t < 0) t = -t;
        k = (k % t + t) % t;    //相当于求上面的K`
        b1 = b1 + n1*k;
        n1 = n1 / d * n2;
    
    if(flag)
        return -1;     //无解
/******************求正整数解******************/
    if(b1==0)    //如果解为0,而题目要正整数解,显然不行
        b1=n1;    //n1刚好为所有ni的最小公倍数,就是解了
/******************求正整数解******************/
    return b1;    //形成的解:b1, b1+n1, b1+2n1,..., b1+xni...

int main()

    int i;
    scanf("%d",&group);
    for(i=0;i<group;i++)
    //X mod n[i] = a[i] ,n[i]两两之间不一定互质做法
        scanf ("%lld%lld",&n[i],&a[i]);
        a[i]%=n[i];
    
    printf ("%lld\\n",solve());
    return 0;


STL全排列函数

bool next_permutation(begin,end);


二分图匹配之最大匹配(匈牙利算法)

int l,r,link[N];//l为左集合点数,r为右集合点数
bool v[N],g[N][N];//编号为0~n-1
bool dfs(int u)

    int i;
    for(i=0;i<r;i++)
        if(g[u][i]&&!v[i])
        
            v[i]=true;
            if(link[i]==-1||dfs(link[i]))
            
                link[i]=u;
                return true;
            
        
    return false;

int hungary()

    int i,res=0;
    memset(link,-1,sizeof(link));
    for(i=0;i<l;i++)
    
        memset(v,false,sizeof(v));
        if(dfs(i))
            res++;
    
    return res;



树上任意两点距离之和的平均数

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-8
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
struct edge

    int v,to,x;
e[2*N];
int h[M],p;
__int64 n;
void add_edge(int u,int v,int x)

    e[p].v=v;
    e[p].x=x;
    e[p].to=h[u];
    h[u]=p++;

double dp[M];
__int64 sum[M];
void dfs(int root,int father)

   sum[root]=1;
   for(int i=h[root];i+1;i=e[i].to)
    
        int son=e[i].v;
        int len=e[i].x;
        if(son==father)
            continue;
        dfs(son,root);
        sum[root]+=sum[son];
        dp[root]+=dp[son]+(sum[son]*(n-sum[son]))*(double)len;
   

int main()

    p=0;
    memset(h,-1,sizeof(h));
    memset(sum,0,sizeof(sum));
    memset(dp,0,sizeof(dp));
    scanf("%I64d",&n);
    /*建树*/
    dfs(1,-1);//点为1~n
    __int64 s=(n*(n-1)/2);
    printf("%.2f\\n",dp[1]/s);
    return 0;


最小生成树prim邻接表实现(时间复杂度O(elogn))

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-8
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
struct edge

    int v,to,x;
e[2*N],w[M*2];
bool v[M];
int h[M],p,k,l[M];
__int64 n;
struct node

    int u,v,d;
    bool operator < (const node &a) const
    
       return d>a.d;//最小值优先
    
    node()
    node(int _u,int _v,int _d):u(_u),v(_v),d(_d)
;
void add_edge(int u,int v,int x)

    e[p].v=v;
    e[p].x=x;
    e[p].to=h[u];
    h[u]=p++;

void add_newedge(int u,int v,int x)

    w[k].v=v;
    w[k].x=x;
    w[k].to=l[u];
    l[u]=k++;

int main()

    int t,i,m,a,b,c;
    __int64 ans;
    node u;
    priority_queue<node> q;
    scanf("%d",&t);
    while(t--)
    
        k=p=0;ans=0;
        while(!q.empty())
            q.pop();
        scanf("%I64d%d",&n,&m);
        for(i=1;i<=n;i++)
        
            h[i]=-1;
            l[i]=-1;
            v[i]=false;
        
        for(i=0;i<m;i++)
        
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c);
            add_edge(b,a,c);
        
        for(i=h[1];i+1;i=e[i].to)
            q.push(node(1,e[i].v,e[i].x));
        v[1]=true;
        while(!q.empty())
        
            u=q.top();
            q.pop();
            if(v[u.v])
                continue;
            ans+=u.d;
            add_newedge(u.u,u.v,u.d);
            add_newedge(u.v,u.u,u.d);
            v[u.v]=true;
            for(i=h[u.v];i+1;i=e[i].to)
                if(!v[e[i].v])
                    q.push(node(u.v,e[i].v,e[i].x));
        
        printf("%I64d\\n",ans);
    
    return 0;


矩阵乘法

对于线性递推式,例如f(n)=2f(n-4)-3f(n-2)+4f(n-1),其对应矩阵的构造方法为:在右上角的(n-1)*(n-1)的小矩阵中的主对角线上填1,矩阵第n行填对应的系数,其它地方都填0


const int N = 2;
const int M = 40;
const int inf = 1000000007;
const int mod = 1000000007;
typedef struct node

	__int64 a[N][N];
	void Init()
	
		memset(a,0,sizeof(a));
		for(int i=0;i<N;i++)
			a[i][i]=1;
	
matrix;
matrix mul(matrix a,matrix b)//矩阵乘法

	matrix ans;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		
			ans.a[i][j]=0;
			for(int k=0;k<N;k++)
				ans.a[i][j]+=(a.a[i][k]*b.a[k][j])%mod;
			ans.a[i][j]%=mod;
		
	return ans;

matrix add(matrix a,matrix b)//矩阵加法

	matrix ans;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			ans.a[i][j]=(a.a[i][j]+b.a[i][j])%mod;
	return ans;

matrix pow(matrix a,int n)//求a^n

	matrix ans;
	ans.Init();
	while(n)
	
		if(n%2)
			ans=mul(ans,a);
		n/=2;
		a=mul(a,a);
	
	return ans;


StoerWagner算法(无向图全局最小割 时间复杂度O(n^3) 选定一个源点s和一个汇点t,求最大流最小)

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-9
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 305;
const int M = 10005;
const int mod = 1000000007;
const int inf = 100000007;
int Map[N][N];
int v[N], dis[N];
bool vis[N];
int StoerWagner(int n)
    int i,j,res=inf;
    for(i=0;i<n;i++)
        v[i]=i;
    while(n>1)
        int k=1,pre=0;
        for(i=1;i<n;i++)
            dis[v[i]]=Map[v[0]][v[i]];
            if(dis[v[i]]>dis[v[k]])
                k=i;
        
        memset(vis,0,sizeof(vis));
        vis[v[0]]=true;
        for(i=1;i<n;i++)
            if(i==n-1)
                res=min(res,dis[v[k]]);
                for(j=0;j<n;j++)
                    Map[v[pre]][v[j]] += Map[v[j]][v[k]];
                    Map[v[j]][v[pre]] += Map[v[j]][v[k]];
                
                v[k] = v[-- n];
            
            vis[v[k]] = true;
            pre = k;
            k = -1;
            for(j = 1; j < n; j ++)
                if(!vis[v[j]])
                    dis[v[j]] += Map[v[pre]][v[j]];
                    if(k == -1 || dis[v[k]] < dis[v[j]])
                        k = j;
                
        
    
    return res;


int main()

    int n,m,u,v,w,s,i;
    while(scanf("%d%d%d",&n,&m,&s)&&(n||m||s))
    
        memset(Map,0,sizeof(Map));
        for(i=0;i<m;i++)
        
            scanf("%d%d%d",&u,&v,&w);
            Map[u-1][v-1]+=w;
            Map[v-1][u-1]+=w;
        
        printf("%d\\n",StoerWagner(n));
    
    return 0;



AC自动机(多模式匹配)

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-9
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 1001;
const int mod = 1000000007;
const int inf = 100000007;
char keyword[M];//输入的一系列模式串
char s[N];//长串
int ans;
struct node

	int val;//是否为该单词的最后一个节点
	node *next[26];//Tire每个节点的子节点个数
	node *fail;//失败指针
	node()//构造函数初始化
	
		val = 0;
		for(int i = 0; i < 26; i++)
			next[i] = NULL;
		fail = NULL;
	
;
node *root;
void insert(char *s)//构造前缀树

	int n = strlen(s);
	node *curr = root;
	for(int i = 0; i < n; i++)
	
		int c = s[i] - 'A';
		if(curr->next[c] == NULL)
			curr->next[c] = new node;
		curr = curr->next[c];
	
	curr->val++;//在单词的最后一个节点val+1,代表一个单词

void build()//用bfs为每个节点设定fail指针

    int i;
    node *temp,*p;
	root->fail = NULL;//root的失败指针指向自己或者NULL
	queue <node*> Q;
	Q.push(root);//把root加入队列
	while(!Q.empty())
	
		temp = Q.front();
		Q.pop();
		for(i = 0; i < 26; i++)
		
			if(temp->next[i] == NULL)
				continue;
			if(temp == root)
				temp->next[i]->fail = root;
			else
			
				p = temp->fail;//p指向h节点所指的节点,也就是root
				while(p != NULL)
				
					if(p->next[i] != NULL)
					
						temp->next[i]->fail = p->next[i];
						break;
					
					p = p->fail;
				
				if(p == NULL)
					temp->next[i]->fail = root;
			
			Q.push(temp->next[i]);
		
	

void find(char *s)

	int n = strlen(s);
	node *p = root;
	for(int i = 0; i < n; i++)
	
		int c = s[i] - 'A';//c=0~25
		while(p != root && p->next[c] == NULL)
			p = p->fail;//p指向p的失败指针所指向的节点
		p = p->next[c];//p指向c节点
		if(p == NULL)
			p = root;
		node *temp = p;
		while(temp != root&&temp->val!=-1)
		
            ans += temp->val;
            temp->val = -1;//将val信息置为-1,表示已经出现过
            temp = temp->fail;//temp指向e的失败指针所指向的节点继续查找
		
	

void del(node *p)//不同题不同的查询

	for(int i = 0; i < 26; i++)
	
		if(p->next[i] != NULL)
			del(p->next[i]);
	
	free(p);

int main()//假设有N个模式,平均长度为L;文章长度为M。建立Trie树:O(N*L) 建立fail指针:O(N*L) 模式匹配:O(M*L) 所以,总时间复杂度为:O((N+M)*L)

	int t;
	scanf("%d", &t);
	while(t--)
	
		ans = 0;
		root = new node;
		int n;
		scanf("%d",&n);
		while(n--)
		
			scanf("%s",keyword);
			insert(keyword);
		
		build();
		scanf("%s",s);
		find(s);
		//del(root);/*杭电G++提交的时候如果不释放可能会MLE,而FZU、POJ等释放可能会TLE,视情况而定*/
		printf("%d\\n",ans);
	
	return 0;




2-SAT算法判可行性模板(时间复杂度O(m))

struct edge

    int to,next;
e[10*M];
int n,p,k,h[N],dfn[N],low[N],belong[N],ans;
bool instack[N];
stack<int> s;
void add_edge(int u,int v)

    e[p].to=v;
    e[p].next=h[u];
    h[u]=p++;

void Clear()

    ans=k=p=0;
    while(!s.empty())
        s.pop();
    memset(h,-1,sizeof(h));
    memset(instack,false,sizeof(instack));
    memset(dfn,0,sizeof(dfn));
    memset(belong,0,sizeof(belong));

void Tarjan(int u)

    int i,v,Top;
    dfn[u]=low[u]=++k;
    s.push(u);
    instack[u]=true;
    for(i=h[u];i+1;i=e[i].next)
    
        v=e[i].to;
        if(!dfn[v])
        
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        
        else if(instack[v])
            low[u]=min(dfn[v],low[u]);
    
    if(low[u]==dfn[u])
    
        ans++;
        while(!s.empty())
        
            Top=s.top();
            s.pop();
            belong[Top]=ans;
            instack[Top]=false;
            if(Top==u)
                break;
        
    

int a[M],b[M],c[M];
void mapping(int x)
//建图,根据题目来,边的含义为"必须"
    for(int i=0;i<=x;i++)
        if(c[i]==2)
        
            add_edge(a[i]+n,b[i]);
            add_edge(b[i]+n,a[i]);
        
        else if(c[i]==1)
        
            add_edge(a[i],b[i]);
            add_edge(b[i],a[i]);
            add_edge(a[i]+n,b[i]+n);
            add_edge(b[i]+n,a[i]+n);
        
        else
        
            add_edge(a[i],b[i]+n);
            add_edge(b[i],a[i]+n);
        

bool judge(int x)

    int i;
    Clear();
    mapping(x);
    for(i=0;i<2*n;i++)
        if(!dfn[i])
            Tarjan(i);
    for(i=0;i<n;i++)
        if(belong[i]==belong[i+n])
            return false;
    return true;


KM算法模板(求解带权二分图最优匹配)

int g[N][N];//主函数里建图
int lx[N],ly[N];
int match[N];
bool visx[N],visy[N];
int slack[N];
bool dfs(int cur,int n)

    visx[cur]=true;
    for(int y=1;y<=n;y++)
    
        if(visy[y])
            continue;
        int t=lx[cur]+ly[y]-g[cur][y];
        if(!t)
        
            visy[y]=true;
            if(match[y]==-1||dfs(match[y],n))
            
                match[y]=cur;
                return true;
            
        
        else if(slack[y]>t)
            slack[y]=t;
    
    return false;

int KM(int n)//时间复杂度O(n^3) 实现带权二分图匹配
//两个集合的点数均为n,点数不相同可以通过补点加0边实现转化
    memset(match,-1,sizeof(match));
    memset(ly,0,sizeof(ly));
    for(int i=1;i<=n;i++)
    
        lx[i]=-inf;
        for(int j=1;j<=n;j++)
            if(g[i][j]>lx[i])
                lx[i]=g[i][j];
    
    for(int x=1;x<=n;x++)
    
        for(int i=1;i<=n;i++)
            slack[i]=inf;
        while(1)
        
            memset(visx,false,sizeof(visx));
            memset(visy,false,sizeof(visy));
            if(dfs(x,n))
                break;
            int d=inf;
            for(int i=1;i<=n;i++)
            
                if(!visy[i]&&d>slack[i])
                    d=slack[i];
            
            for(int i=1;i<=n;i++)
            
                if(visx[i])
                    lx[i]-=d;
            
            for(int i=1;i<=n;i++)
            
                if(visy[i])
                    ly[i]+=d;
                else
                    slack[i]-=d;
            
        
    
    int result=0;
    for(int i=1;i<=n;i++)
        if(match[i]>-1)
            result+=g[match[i]][i];
    return result;



RMQ模板

int s[50005],n,maxnum[50005][20],minnum[50005][20];
void RMQ()   		//预处理  O(nlogn)

	int i,j;
	int m=(int)(log(n*1.0)/log(2.0));
	for(i=1;i<=n;i++)
		maxnum[i][0]=minnum[i][0]=s[i];
	for(j=1;j<=m;j++)
		for(i=1;i+(1<<j)-1<=n;i++)
		
			maxnum[i][j]=max(maxnum[i][j-1],maxnum[i+(1<<(j-1))][j-1]);
			minnum[i][j]=min(minnum[i][j-1],minnum[i+(1<<(j-1))][j-1]);
		

int Ask_MAX (int a,int b) 	//O(1)

	int k=int(log(b-a+1.0)/log(2.0));
	return max(maxnum[a][k],maxnum[b-(1<<k)+1][k]);

int Ask_MIN (int a,int b) 	//O(1)

	int k=int(log(b-a+1.0)/log(2.0));
	return min(minnum[a][k],minnum[b-(1<<k)+1][k]);


容斥原理模板

int k,prime[N];
__int64 factor[M];
__int64 Exclusion(__in64 n)

    int i,j,p=0,q;
    __in64 sum=0;
    factor[p++]=-1;
    for(i=0;i<k;i++)
    
        q=p;
        for(j=0;j<q;j++)
            factor[p++]=factor[j]*prime[i]*(-1);
    
    for(i=1;i<p;i++)
        sum+=n/factor[i];
    return sum;


KMP算法模板(字符串匹配)

char s2[N],s[N*100];  
int n[N];  
void getnext()

    int i=0,j=-1,l=strlen(s2);
    n[0]=-1;
    while(i<l)
        if(j==-1||s2[i]==s2[j])
        	n[++i]=++j;
        else
            j=n[j];
 
int kmp()  
  
    getnext();  
    int i=0,j=0,k=0,len=strlen(s),l=strlen(s2);  
    while(i<len)  
      
        if(j==-1|s[i]==s2[j])  
            i++,j++;  
        else  
            j=n[j];  
        if(j==l)  
            k++,j=n[j];  
      
    return k;  


字典树(Trie树)模板

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 15;
const int M = 26;
const int inf = 100000000;
const int mod = 2009;
struct tree

	int a[M],t;
s[1000005];
char ch[N];
int p;
void init(int x)

	s[x].t=0;
	memset(s[x].a,-1,sizeof(s[x].a));

void buildtree()

	int i,k=0;
	for(i=0;ch[i]!='\\0';i++)
	
		if(s[k].a[ch[i]-'a']==-1)
		
			s[k].a[ch[i]-'a']=p;
			init(p++);
		
		k=s[k].a[ch[i]-'a'];
		s[k].t++;
		

int query()

	int i,k=0;
	for(i=0;ch[i]!='\\0';i++)
	
		if(s[k].a[ch[i]-'a']==-1)
			return 0;
		k=s[k].a[ch[i]-'a'];
	
	return s[k].t;

int main()

    int n,m,i;
    while(~scanf("%d",&n))
    
    	p=0;init(p++);
    	for(i=0;i<n;i++)
    	
	    	scanf("%s",ch);
    		buildtree();
	    
    	scanf("%d",&m);
    	for(i=0;i<m;i++)
    	
	    	scanf("%s",ch);
    		printf("%d\\n",query());
	    
    
    return 0;




Manacher算法O(n)求解回文串问题

const int N=20005;  
char s[N*2];  
int p[N*2],top[N*2],tail[N*2];  
void Manacher()   
  
    int len = strlen(s), id = 0, maxlen = 0;  
    for (int i = len;i >= 0;--i)   
        s[i + i + 2] = s[i];  
        s[i + i + 1] = '#';  
     
 s[0] = '*';  
 for (int i = 2;i < 2 * len + 1;++i)   
        if (p[id] + id > i)p[i] = min(p[2 * id - i], p[id] + id - i);  
        else p[i] = 1;  
        while (s[i - p[i]] == s[i + p[i]])++p[i];  
        if (id + p[id] < i + p[i])id = i;  
        if (maxlen < p[i])maxlen = p[i];  
      
    //cout << maxlen - 1 << endl;  
  




欧拉函数模板//计算n以内与n互质的数的个数

int euler(int n)  
  
    int ans=1,i; 
    for(i=2;i*i<=n;i++)  
      
        if(n%i==0)  
          
            n/=i;  
            ans*=i-1;  
            while(n%i==0)  
              
                n/=i;  
                ans*=i;  
              
          
      
    if(n>1)  
        ans*=n-1;  
    return ans;  



最大流SAP算法(邻接矩阵)

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 205;
const int M = 1005;
const int inf = 1000000007;
const int mod = 2009;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int Map[N][N];//存图
int pre[N];//记录当前点的前驱
int level[N];//记录距离标号
int gap[N];//gap常数优化
int NV,NE;
//入口参数vs源点,vt汇点
int SAP(int vs,int vt,int n)

    memset(pre,-1,sizeof(pre));
    memset(level,0,sizeof(level));
    memset(gap,0,sizeof(gap));
    gap[0]=n;
    int v,u=pre[vs]=vs,maxflow=0,aug=inf;
    while(level[vs]<n)
    
        //寻找可行弧
        for(v=1;v<=n;v++)
            if(Map[u][v]>0&&level[u]==level[v]+1)
                break;
        if(v<=n)
        
            pre[v]=u;
            u=v;
            if(v==vt)
            
                aug=inf;
                //寻找当前找到的一条路径上的最大流
                for(int i=v;i!=vs;i=pre[i])
                    if(aug>Map[pre[i]][i])
                        aug=Map[pre[i]][i];
                maxflow+=aug;
                //更新残留网络
                for(int i=v;i!=vs;i=pre[i])
                
                    Map[pre[i]][i]-=aug;
                    Map[i][pre[i]]+=aug;
                
                u=vs;//从源点开始继续搜
            
        
        else
        
            //找不到可行弧
            int minlevel=n;
            //寻找与当前点相连接的点中最小的距离标号
            for(v=1;v<=n;v++)
                if(Map[u][v]>0&&minlevel>level[v])
                    minlevel=level[v];
            gap[level[u]]--;//(更新gap数组)当前标号的数目减1;
            if(gap[level[u]]==0)
                break;//出现断层
            level[u]=minlevel+1;
            gap[level[u]]++;
            u=pre[u];
        
    
    return maxflow;

int main()

    int n,m,u,v,cap;
    while(~scanf("%d%d",&n,&m))
    
        memset(Map,0,sizeof(Map));
        for(int i=1;i<=m;i++)
        
            scanf("%d%d%d",&u,&v,&cap);
            Map[u][v]+=cap;
        
        printf("%d\\n",SAP(1,n,n));//源点为1,汇点为n,n个结点的最大流
    
    return 0;



最大流SAP算法(邻接表)

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 205;
const int M = 40005;//邻接表要开边数的2倍
const int inf = 1000000007;
const int mod = 2009;
struct Edge

    int v,cap,next;
edge[2*M];
int level[N];//标记层次(距离标号)
//间隙优化,定义gap[i]为标号是i的点的个数
//在重标记i时,检查gap[level[i]],若减为0,这算法结束。
int gap[N];
int pre[N];//前驱
int cur[N];
int head[N];
int NV,NE;
//NE为边数,初始化为0;
void add_edge(int u,int v,int cap)

    edge[NE].cap=cap;edge[NE].v=v;
    edge[NE].next=head[u];head[u]=NE++;
    edge[NE].cap=0;edge[NE].v=u;
    edge[NE].next=head[v];head[v]=NE++;

//参数,源点,汇点
int SAP(int vs,int vt,int n)

    bool flag;
    memset(level,0,sizeof(level));
    memset(pre,-1,sizeof(pre));
    memset(gap,0,sizeof(gap));
    //cur[i]保存的是当前弧
    for(int i=0;i<=NV;i++)
        cur[i]=head[i];
    int u=pre[vs]=vs;//源点的pre还是其本身
    int maxflow=0,aug=-1;
    gap[0]=n;
    while(level[vs]<NV)
    
        flag=true;
        for(int &i=cur[u];i!=-1;i=edge[i].next)
        
            int v=edge[i].v;//v是u的后继
            //寻找可行弧
            if(edge[i].cap&&level[u]==level[v]+1)
            
                //aug表示增广路的可改进量
                aug==-1?(aug=edge[i].cap):(aug=min(aug,edge[i].cap));
                pre[v]=u;
                u=v;
                //如果找到一条增广路
                if(v==vt)
                
                    maxflow+=aug;//更新最大流;
                    //路径回溯更新残留网络
                    for(u=pre[v];v!=vs;v=u,u=pre[u])
                    
                        //前向弧容量减少,反向弧容量增加
                        edge[cur[u]].cap-=aug;
                        edge[cur[u]^1].cap+=aug;
                    
                    aug=-1;
                
                flag=false;
                break;
            
        
        if(!flag)
            continue;
        int minlevel=n;
        //寻找与当前点相连接的点中最小的距离标号(重标号)
        for(int i=head[u];i!=-1;i=edge[i].next)
        
            int v=edge[i].v;
            if(edge[i].cap&&minlevel>level[v])
            
                cur[u]=i;//保存弧
                minlevel=level[v];
            
        
        if((--gap[level[u]])==0)
            break;//更新gap数组后如果出现断层,则直接退出。
        level[u]=minlevel+1;//重标号
        gap[level[u]]++;//距离标号为level[u]的点的个数+1;
        u=pre[u];//转当前点的前驱节点继续寻找可行弧
    
    return maxflow;

int main()

    int m;//边的条数
    while(~scanf("%d%d",&NV,&m))
    
        memset(head,-1,sizeof(head));
        NE=0;
        for(int i=1;i<=m;i++)
        
            int u,v,cap;
            scanf("%d%d%d",&u,&v,&cap);
            add_edge(u,v,cap);
        
        printf("%d\\n",SAP(1,NV,NV));
    
    return 0;



最大连续子序列和

last=ans=0;
for(i=1;i <= n;i++)

     last=f_max(0,last)+b[i];
     ans=f_max(ans,last);



二分查找模板,可以自己改成数组传递

bool searchs(int x,int len)

    int left=0,right=len-1;
    while(left<=right)
    
        int mid=(left+right)/2;
        if(x>s[mid])
            left=mid+1;
        else if(x==s[mid])
            return true;
        else
            right=mid-1;
    
    return false;


最长上升子序列LIS模板

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 100005;
const int M = 2010;
const int inf = 2147483647;
const int mod = 2009;
int  a[N], f[N], d[N];    // f[i]用于记录 a[0...i]的最大长度 
int bsearch(const int *f, int size, const int &a) 
 
    int  l=0, r=size-1; 
    while( l <= r )
     
        int  mid = (l+r)>>1; 
        if( a > d[mid-1] && a <= d[mid] ) 
            return mid;                // >&&<= 换为: >= && < 
        else if( a <d[mid] ) 
                r = mid-1; 
        else l = mid+1; 
     
 
int LIS(const int *a, const int &n)
 
    int  i, j, size = 1; 
    d[0] = a[0]; f[0] = 1; 
    for( i=1; i < n; ++i )
     
        if( a[i] <= d[0] )             // <= 换为: < 
            j = 0;               
        else if( a[i] > d[size-1] ) // > 换为: >=  
            j = size++;            
        else 
            j = bsearch(d, size, a[i]); 

        d[j] = a[i]; f[i] = j+1; 
     
    return size; 
 
int main()
 
    int  t,i, n; 
    scanf("%d",&t);
    while(t--)
     
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        scanf("%d",&n);
        for( i=0; i < n; ++i ) 
            scanf("%d", &a[i]);
        printf("%d\\n",LIS(a, n));//求最大递增/上升子序列(如果为最大非降子序列,只需把上面的注释部分给与替换)
     
    return 0; 


强连通分量Tarjan算法模板

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 10005;
const int inf = 100000000;
const int mod = 2009;
struct edge

    int to,next;
e[10*N];
int p,k,h[N],dfn[N],low[N],belong[N],ans;
bool instack[N];
stack<int> s;
void add_edge(int u,int v)

    e[p].to=v;
    e[p].next=h[u];
    h[u]=p++;

void Clear()

    ans=k=p=0;
    while(!s.empty())
        s.pop();
    memset(h,-1,sizeof(h));
    memset(instack,false,sizeof(instack));
    memset(dfn,0,sizeof(dfn));
    memset(belong,0,sizeof(belong));

void Tarjan(int u)//Tarjan算法求有向图的强连通分量,时间复杂度O(n+m)

    int i,v,Top;
    dfn[u]=low[u]=++k;
    s.push(u);//入栈
    instack[u]=true;//标记在栈中
    for(i=h[u];i+1;i=e[i].next)
    //枚举v的每一条边
        v=e[i].to;//v所邻接的边
        if(!dfn[v])
        //未被访问
            Tarjan(v);//继续向下找
            low[u]=min(low[u],low[v]);//更新结点v所能到达的最小次数层
        
        else if(instack[v])
            low[u]=min(dfn[v],low[u]);
    
    if(low[u]==dfn[u])
    
        ans++;
        while(!s.empty())
        
            Top=s.top();
            s.pop();
            belong[Top]=ans;//出栈结点t属于cnt标号的强连通分量
            instack[Top]=false;//标记不在栈中
            if(Top==u)
                break;
        
    


大数模板,涵盖各种运算(+,-,*,/,%,...),bignum的数据类型,定义变量与基本数据类型一样,例如定义一个数组,可直接bignum s[100];

不过读入需要cin

/*
+,-,*,/,% 可直接使用.
CIN读入
bignum数据类型
*/
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<iostream>
using namespace std;
#define DIGIT    4
#define DEPTH    10000
#define MAX     100//大数计算位数
typedef int bignum_t[MAX+1];
int read(bignum_t a,istream& is=cin)
    char buf[MAX*DIGIT+1],ch;
    int i,j;
    memset((void*)a,0,sizeof(bignum_t));
    if (!(is>>buf))    return 0;
    for (a[0]=strlen(buf),i=a[0]/2-1;i>=0;i--)
        ch=buf[i],buf[i]=buf[a[0]-1-i],buf[a[0]-1-i]=ch;
    for (a[0]=(a[0]+DIGIT-1)/DIGIT,j=strlen(buf);j<a[0]*DIGIT;buf[j++]='0');
    for (i=1;i<=a[0];i++)
        for (a[i]=0,j=0;j<DIGIT;j++)
            a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0';
    for (;!a[a[0]]&&a[0]>1;a[0]--);
    return 1;


void write(const bignum_t a,ostream& os=cout)
    int i,j;
    for (os<<a[i=a[0]],i--;i;i--)
        for (j=DEPTH/10;j;j/=10)
            os<<a[i]/j%10;


int comp(const bignum_t a,const bignum_t b)
    int i;
    if (a[0]!=b[0])
        return a[0]-b[0];
    for (i=a[0];i;i--)
        if (a[i]!=b[i])
            return a[i]-b[i];
    return 0;


int comp(const bignum_t a,const int b)
    int c[12]=1;
    for (c[1]=b;c[c[0]]>=DEPTH;c[c[0]+1]=c[c[0]]/DEPTH,c[c[0]]%=DEPTH,c[0]++);
    return comp(a,c);


int comp(const bignum_t a,const int c,const int d,const bignum_t b)
    int i,t=0,O=-DEPTH*2;
    if (b[0]-a[0]<d&&c)
        return 1;
    for (i=b[0];i>d;i--)
        t=t*DEPTH+a[i-d]*c-b[i];
        if (t>0) return 1;
        if (t<O) return 0;
    
    for (i=d;i;i--)
        t=t*DEPTH-b[i];
        if (t>0) return 1;
        if (t<O) return 0;
    
    return t>0;


void add(bignum_t a,const bignum_t b)
    int i;
    for (i=1;i<=b[0];i++)
        if ((a[i]+=b[i])>=DEPTH)
            a[i]-=DEPTH,a[i+1]++;
    if (b[0]>=a[0])
        a[0]=b[0];
    else
        for (;a[i]>=DEPTH&&i<a[0];a[i]-=DEPTH,i++,a[i]++);
    a[0]+=(a[a[0]+1]>0);


void add(bignum_t a,const int b)
    int i=1;
    for (a[1]+=b;a[i]>=DEPTH&&i<a[0];a[i+1]+=a[i]/DEPTH,a[i]%=DEPTH,i++);
    for (;a[a[0]]>=DEPTH;a[a[0]+1]=a[a[0]]/DEPTH,a[a[0]]%=DEPTH,a[0]++);


void sub(bignum_t a,const bignum_t b)
    int i;
    for (i=1;i<=b[0];i++)
        if ((a[i]-=b[i])<0)
            a[i+1]--,a[i]+=DEPTH;
    for (;a[i]<0;a[i]+=DEPTH,i++,a[i]--);
    for (;!a[a[0]]&&a[0]>1;a[0]--);


void sub(bignum_t a,const int b)
    int i=1;
    for (a[1]-=b;a[i]<0;a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH,i++);
    for (;!a[a[0]]&&a[0]>1;a[0]--);


void sub(bignum_t a,const bignum_t b,const int c,const int d)
    int i,O=b[0]+d;
    for (i=1+d;i<=O;i++)
        if ((a[i]-=b[i-d]*c)<0)
            a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH;
    for (;a[i]<0;a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH,i++);
    for (;!a[a[0]]&&a[0]>1;a[0]--);


void mul(bignum_t c,const bignum_t a,const bignum_t b)
    int i,j;
    memset((void*)c,0,sizeof(bignum_t));
    for (c[0]=a[0]+b[0]-1,i=1;i<=a[0];i++)
        for (j=1;j<=b[0];j++)
            if ((c[i+j-1]+=a[i]*b[j])>=DEPTH)
                c[i+j]+=c[i+j-1]/DEPTH,c[i+j-1]%=DEPTH;
    for (c[0]+=(c[c[0]+1]>0);!c[c[0]]&&c[0]>1;c[0]--);


void mul(bignum_t a,const int b)
    int i;
    for (a[1]*=b,i=2;i<=a[0];i++)
        a[i]*=b;
        if (a[i-1]>=DEPTH)
            a[i]+=a[i-1]/DEPTH,a[i-1]%=DEPTH;
    
    for (;a[a[0]]>=DEPTH;a[a[0]+1]=a[a[0]]/DEPTH,a[a[0]]%=DEPTH,a[0]++);
    for (;!a[a[0]]&&a[0]>1;a[0]--);


void mul(bignum_t b,const bignum_t a,const int c,const int d)
    int i;
    memset((void*)b,0,sizeof(bignum_t));
    for (b[0]=a[0]+d,i=d+1;i<=b[0];i++)
        if ((b[i]+=a[i-d]*c)>=DEPTH)
            b[i+1]+=b[i]/DEPTH,b[i]%=DEPTH;
    for (;b[b[0]+1];b[0]++,b[b[0]+1]=b[b[0]]/DEPTH,b[b[0]]%=DEPTH);
    for (;!b[b[0]]&&b[0]>1;b[0]--);


void div(bignum_t c,bignum_t a,const bignum_t b)
    int h,l,m,i;
    memset((void*)c,0,sizeof(bignum_t));
    c[0]=(b[0]<a[0]+1)?(a[0]-b[0]+2):1;
    for (i=c[0];i;sub(a,b,c[i]=m,i-1),i--)
        for (h=DEPTH-1,l=0,m=(h+l+1)>>1;h>l;m=(h+l+1)>>1)
            if (comp(b,m,i-1,a)) h=m-1;
            else l=m;
    for (;!c[c[0]]&&c[0]>1;c[0]--);
    c[0]=c[0]>1?c[0]:1;


void div(bignum_t a,const int b,int& c)
    int i;
    for (c=0,i=a[0];i;c=c*DEPTH+a[i],a[i]=c/b,c%=b,i--);
    for (;!a[a[0]]&&a[0]>1;a[0]--);


void sqrt(bignum_t b,bignum_t a)
    int h,l,m,i;
    memset((void*)b,0,sizeof(bignum_t));
    for (i=b[0]=(a[0]+1)>>1;i;sub(a,b,m,i-1),b[i]+=m,i--)
        for (h=DEPTH-1,l=0,b[i]=m=(h+l+1)>>1;h>l;b[i]=m=(h+l+1)>>1)
            if (comp(b,m,i-1,a)) h=m-1;
            else l=m;
    for (;!b[b[0]]&&b[0]>1;b[0]--);
    for (i=1;i<=b[0];b[i++]>>=1);


int length(const bignum_t a)
    int t,ret;
    for (ret=(a[0]-1)*DIGIT,t=a[a[0]];t;t/=10,ret++);
    return ret>0?ret:1;


int digit(const bignum_t a,const int b)
    int i,ret;
    for (ret=a[(b-1)/DIGIT+1],i=(b-1)%DIGIT;i;ret/=10,i--);
    return ret%10;


int zeronum(const bignum_t a)
    int ret,t;
    for (ret=0;!a[ret+1];ret++);
    for (t=a[ret+1],ret*=DIGIT;!(t%10);t/=10,ret++);
    return ret;


void comp(int* a,const int l,const int h,const int d)
    int i,j,t;
    for (i=l;i<=h;i++)
        for (t=i,j=2;t>1;j++)
            while (!(t%j))
                a[j]+=d,t/=j;


void convert(int* a,const int h,bignum_t b)
    int i,j,t=1;
    memset(b,0,sizeof(bignum_t));
    for (b[0]=b[1]=1,i=2;i<=h;i++)
        if (a[i])
            for (j=a[i];j;t*=i,j--)
                if (t*i>DEPTH)
                    mul(b,t),t=1;
    mul(b,t);


void combination(bignum_t a,int m,int n)
    int* t=new int[m+1];
    memset((void*)t,0,sizeof(int)*(m+1));
    comp(t,n+1,m,1);
    comp(t,2,m-n,-1);
    convert(t,m,a);
    delete []t;


void permutation(bignum_t a,int m,int n)
    int i,t=1;
    memset(a,0,sizeof(bignum_t));
    a[0]=a[1]=1;
    for (i=m-n+1;i<=m;t*=i++)
        if (t*i>DEPTH)
            mul(a,t),t=1;
    mul(a,t);


#define SGN(x) ((x)>0?1:((x)<0?-1:0))
#define ABS(x) ((x)>0?(x):-(x))

int read(bignum_t a,int &sgn,istream& is=cin)
    char str[MAX*DIGIT+2],ch,*buf;
    int i,j;
    memset((void*)a,0,sizeof(bignum_t));
    if (!(is>>str)) return 0;
    buf=str,sgn=1;
    if (*buf=='-') sgn=-1,buf++;
    for (a[0]=strlen(buf),i=a[0]/2-1;i>=0;i--)
        ch=buf[i],buf[i]=buf[a[0]-1-i],buf[a[0]-1-i]=ch;
    for (a[0]=(a[0]+DIGIT-1)/DIGIT,j=strlen(buf);j<a[0]*DIGIT;buf[j++]='0');
    for (i=1;i<=a[0];i++)
        for (a[i]=0,j=0;j<DIGIT;j++)
            a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0';
    for (;!a[a[0]]&&a[0]>1;a[0]--);
    if (a[0]==1&&!a[1]) sgn=0;
    return 1;


struct bignum
    bignum_t num;
    int sgn;
public:
inline bignum()memset(num,0,sizeof(bignum_t));num[0]=1;sgn=0;
//inline int operator!()return num[0]==1&&!num[1];
inline bignum& operator=(const bignum& a)memcpy(num,a.num,sizeof(bignum_t));sgn=a.sgn;return *this;
inline bignum& operator=(const int a)memset(num,0,sizeof(bignum_t));num[0]=1;sgn=SGN(a);add(num,sgn*a);return *this;;
inline bignum& operator+=(const bignum& a)if(sgn==a.sgn)add(num,a.num);else if(sgn&&a.sgn)int ret=comp(num,a.num);if(ret>0)sub(num,a.num);else if(ret<0)bignum_t t;
    memcpy(t,num,sizeof(bignum_t));memcpy(num,a.num,sizeof(bignum_t));sub(num,t);sgn=a.sgn;else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0;else if(!sgn)memcpy(num,a.num,sizeof(bignum_t)),sgn=a.sgn;return *this;
inline bignum& operator+=(const int a)if(sgn*a>0)add(num,ABS(a));else if(sgn&&a)int ret=comp(num,ABS(a));if(ret>0)sub(num,ABS(a));else if(ret<0)bignum_t t;
    memcpy(t,num,sizeof(bignum_t));memset(num,0,sizeof(bignum_t));num[0]=1;add(num,ABS(a));sgn=-sgn;sub(num,t);else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0;else if(!sgn)sgn=SGN(a),add(num,ABS(a));return *this;
inline bignum operator+(const bignum& a)bignum ret;memcpy(ret.num,num,sizeof(bignum_t));ret.sgn=sgn;ret+=a;return ret;
inline bignum operator+(const int a)bignum ret;memcpy(ret.num,num,sizeof(bignum_t));ret.sgn=sgn;ret+=a;return ret;
inline bignum& operator-=(const bignum& a)if(sgn*a.sgn<0)add(num,a.num);else if(sgn&&a.sgn)int ret=comp(num,a.num);if(ret>0)sub(num,a.num);else if(ret<0)bignum_t t;
    memcpy(t,num,sizeof(bignum_t));memcpy(num,a.num,sizeof(bignum_t));sub(num,t);sgn=-sgn;else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0;else if(!sgn)add(num,a.num),sgn=-a.sgn;return *this;
inline bignum& operator-=(const int a)if(sgn*a<0)add(num,ABS(a));else if(sgn&&a)int ret=comp(num,ABS(a));if(ret>0)sub(num,ABS(a));else if(ret<0)bignum_t t;
    memcpy(t,num,sizeof(bignum_t));memset(num,0,sizeof(bignum_t));num[0]=1;add(num,ABS(a));sub(num,t);sgn=-sgn;else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0;else if(!sgn)sgn=-SGN(a),add(num,ABS(a));return *this;
inline bignum operator-(const bignum& a)bignum ret;memcpy(ret.num,num,sizeof(bignum_t));ret.sgn=sgn;ret-=a;return ret;
inline bignum operator-(const int a)bignum ret;memcpy(ret.num,num,sizeof(bignum_t));ret.sgn=sgn;ret-=a;return ret;
inline bignum& operator*=(const bignum& a)bignum_t t;mul(t,num,a.num);memcpy(num,t,sizeof(bignum_t));sgn*=a.sgn;return *this;
inline bignum& operator*=(const int a)mul(num,ABS(a));sgn*=SGN(a);return *this;
inline bignum operator*(const bignum& a)bignum ret;mul(ret.num,num,a.num);ret.sg

以上是关于各类模板(更新中...)(若有什么特别的需要,可以留下评论)的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统有漏洞吗,若有,如何打补丁?更新升级是自动的吗,若否,命令是啥?

hector slam缺点

STM32 通过DMA收发RS485数据需要特别的电路配合吗

Silverlight:带有文本修剪功能的按钮模板

Hibernate - @Transactional 不起作用有啥特别的原因吗?

python特别的一点:try语句