• 模板库


    个人码风:大括号换行,4格缩进,轻微压行

    注:代码中可能缺少以下缺省源:

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for (register int i=(a); i<=(b); ++i)
    #define per(i, a, b) for (register int i=(a); i>=(b); --i)
    inline int read()
    {
     	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    

    字符串

    KMP

    const int N=1000005;
    char s[N], t[N];
    int len_s, len_t, nxt[N];
    void GetNext(char *s)
    {
        for (int i=2, k=0; i<=len_s; i++)
        {
            while (k && s[i]!=s[k+1]) k=nxt[k];
            if (s[i]==s[k+1]) k++; nxt[i]=k;
        }
    }
    
    void KMP(char *s, char *t)
    {
        for (int i=1, k=0; i<=len_t; i++)
        {
            while (k && t[i]!=s[k+1]) k=nxt[k];
            if (t[i]==s[k+1]) k++; 
            if (k==len_s){printf("%d
    ", i-len_s+1); k=nxt[k];}
        }
    }
    

    SAM

    inline void chkmax(int &x, int y){x<y?(x=y):0;}
    inline void chkmin(int &x, int y){x>y?(x=y):0;}
    const int N=1000005;
    int son[N<<1][100], fa[N], len[N], last, cnt, n;//insert
    int a[N], t[N], size[N];//sort
    int mn[N], mx[N];//Get_N_LCS
    int sum[N];//Get_Kth_Substr
    int dp[N];//Get_N_Substr
    long long ans;//Dif_Substr_Num
    char s[N];
    
    namespace SuffixAutoMaton
    {
    	void clear()//for Dif_Substr_Num
    	{
    		memset(fa, 0, sizeof(fa));
    		memset(len, 0, sizeof(len));
    		memset(son, 0, sizeof(son));
    		ans=0; 
    	}
    	
        void insert(int c)
        {
            int p=last, np=last=++cnt; len[np]=len[p]+1;
            for (; p&&!son[p][c]; p=fa[p]) son[p][c]=np;
            if (!p) fa[np]=1;
            else
            {
                int q=son[p][c]; 
                if (len[p]+1==len[q]) fa[np]=q;
                else
                {
                    int nq=++cnt; len[nq]=len[p]+1;
                    memcpy(son[nq], son[q], sizeof(son[q]));
                    fa[nq]=fa[q]; fa[q]=fa[np]=nq;
                    for (; son[p][c]==q; p=fa[p]) son[p][c]=nq;
                }
            }
            size[np]=1; 
    		//ans+=len[np]-len[fa[np]]; //for Dif_Substr_Num
        }
        
        void Sort()
        {
        	for (int i=1; i<=cnt; i++) t[len[i]]++;
            for (int i=1; i<=cnt; i++) t[i]+=t[i-1];
            for (int i=1; i<=cnt; i++) a[t[len[i]]--]=i;
            for (int i=cnt; i; i--) size[fa[a[i]]]+=size[a[i]];
        }
        
        void build()
        {
            scanf("%s", s+1); last=cnt=1; n=strlen(s+1);
        	for (int i=1; i<=n; i++) insert(s[i]-'A');
        }
        
        void Get_LCS()
        {
            build(); scanf("%s", s+1); 
            int n=strlen(s+1), p=1, Len=0, ans=0;
            for (int i=1; i<=n; i++)
            {
                int c=s[i]-'a';
                if (son[p][c]) p=son[p][c], Len++;
                else
                {
                    for (; p&&!son[p][c]; p=fa[p]);
                    if (p) Len=len[p]+1, p=son[p][c];
                        else p=1, Len=0;
                }
                ans=max(ans, Len);
            }
            printf("%d
    ", ans);
        }
        
        void Get_N_LCS()
        {
            memset(mn, 0x3f, sizeof(mn)); 
    		build(); Sort(); int ans=0;
            while (~scanf("%s", s+1))
            {
                int n=strlen(s+1), p=1, Len=0;
                for (int i=1; i<=n; i++)
                {
                    int c=s[i]-'a';
                    if (son[p][c]) Len++, p=son[p][c], chkmax(mx[p], Len);
                    else
                    {
                        for (; p&&!son[p][c]; p=fa[p]);
                        if (p) Len=len[p]+1, p=son[p][c], chkmax(mx[p], Len);
                            else Len=0, p=1;
                    }
                }
                for (int i=cnt; i; i--)
                {
                    int u=a[i];
                    chkmax(mx[fa[u]], min(mx[u], len[fa[u]]));
                    chkmin(mn[u], mx[u]); mx[u]=0;
                }
            }
            for (int i=1; i<=cnt; i++) chkmax(ans, mn[i]);
            printf("%d
    ", ans);
        }
        
        void Get_Kth_Dif_Substr()
        {
        	Sort();
        	for (int i=1; i<=cnt; i++) sum[i]=size[i]=1; sum[1]=size[1]=0;
        	for (int i=cnt; i; i--) 
            	for (int j=0; j<26; j++) sum[a[i]]+=sum[son[a[i]][j]];
        	int k=read(), u=1; 
    		if (sum[1]<k) {puts("-1"); exit(0);}
            while (k>0)
            {
                for (int i=0; i<26; i++) if (son[u][i])
                {
                    if (sum[son[u][i]]<k) k-=sum[son[u][i]];
                        else{putchar(i+'a'); u=son[u][i]; k--; break;}
                }
            }
            puts("");
        }
        
        void Get_Kth_Substr()
        {
        	Sort();
        	for (int i=1; i<=cnt; i++) sum[i]=size[i]; sum[1]=size[1]=0;
       	    for (int i=cnt; i; i--) 
            	for (int j=0; j<26; j++) sum[a[i]]+=sum[son[a[i]][j]];
    		int k=read(), u=1; if (sum[1]<k) {puts("-1"); exit(0);}
    		while (k>0)
    	    {
    	        for (int i=0; i<26; i++) if (son[u][i])
    	        {
    	            if (sum[son[u][i]]<k) k-=sum[son[u][i]];
    	                else{putchar(i+'a'); u=son[u][i]; k-=size[u]; break;}
    	        }
    	    }
    	    puts("");
    	}
    	
    	void Get_N_Substr()
    	{
    		build(); Sort();
    		for (int i=cnt; i; i--) chkmax(dp[len[a[i]]], size[a[i]]);
    		for (int i=n-1; i; i--) chkmax(dp[i], dp[i+1]);
    		for (int i=1; i<=n; i++) printf("%d
    ", dp[i]);
    	}
    	
    	void Dif_Substr_Num()
    	{
    		int T=read();
    		while (T--) clear(), build(), printf("%lld
    ", ans);
    	}	
    }
    

    SA

    const int N=2000005;
    int sa[N], rnk[N], top[N], tax[N], n, m;
    int h[N], st[N][24], log_2[N];
    char s[N];
    
    namespace SuffixArray
    {
        inline void SuffixSort()
        {
            scanf("%s", s+1); n=strlen(s+1); m=122;
            memset(tax, 0, sizeof(tax));
            for (int i=1; i<=n; i++) tax[rnk[i]=(int)s[i]]++;
            for (int i=1; i<=m; i++) tax[i]+=tax[i-1];
            for (int i=n; i; i--) sa[tax[rnk[i]]--]=i;
            for (int p=1; p<=n; p<<=1)
            {
                int t=0;
                for (int i=n-p+1; i<=n; i++) top[++t]=i;
                for (int i=1; i<=n; i++) if (sa[i]>p) top[++t]=sa[i]-p;
                memset(tax, 0, sizeof(tax));
                for (int i=1; i<=n; i++) tax[rnk[i]]++;
                for (int i=1; i<=m; i++) tax[i]+=tax[i-1];
                for (int i=n; i; i--) sa[tax[rnk[top[i]]]--]=top[i];
                memcpy(top, rnk, sizeof(rnk)); rnk[sa[1]]=t=1;
                for (int i=2; i<=n; i++) 
                    rnk[sa[i]]=(top[sa[i-1]]==top[sa[i]] 
                        && top[sa[i-1]+p]==top[sa[i]+p])? t : ++t;
                if (t==n) break; m=t;
            }
        }
    
        void Height()
        {
            int k=0;
            for (int i=1; i<=n; i++) rnk[sa[i]]=i;
            for (int i=1; i<=n; i++)
            {
                int j=sa[rnk[i]-1]; k?k--:0; 
                while (s[i+k]==s[j+k]) k++; h[rnk[i]]=k;
            }
        }
        
        void ST()
        {
            for (int i=1; i<=n; i++) st[i][0]=h[i+1];
            for (int p=1; (1<<p)<n; p++)
                for (int i=1; i+(1<<p)-1<=n; i++)
                    st[i][p]=min(st[i][p-1], st[i+(1<<(p-1))][p-1]);
            log_2[1]=0;
            for (int i=2; i<=n; i++) log_2[i]=log_2[i>>1]+1;
        }
        
        int LCP(int l, int r)
        {
            int p=log_2[r-l+1];
            return min(st[l][p], st[r-(1<<p)+1][p]);
        }
    }
    

    AC自动机(Trie图)

    const int N=1000005;
    struct node{int fail, num, son[26];}t[N];
    int cnt; char s[N];
    namespace Aho_Corasick_Automaton
    {	
    	void insert(char *s)
    	{
    	    int len=strlen(s+1), p=0;
    	    for (int i=1; i<=len; i++)
    	    {
    	        int c=s[i]-'a';
    	        if (!t[p].son[c]) t[p].son[c]=++cnt;
    	        p=t[p].son[c];
    	    }
    	    t[p].num++;
    	}
    	
    	void build_AC()
    	{
    	    queue<int> q;
    	    for (int i=0; i<26; i++) if (t[0].son[i]) q.push(t[0].son[i]);
    	    while (!q.empty())
    	    {
    	        int now=q.front(), fail=t[now].fail; q.pop();
    	        for (int i=0; i<26; i++)
    	        {
    	            int son=t[now].son[i];
    	            if(son) t[son].fail=t[fail].son[i], q.push(son);
    	                else t[now].son[i]=t[fail].son[i];
    	        }
    	    }
    	}
    	
    	int find(char *s)
    	{
    	    int len=strlen(s+1), pos=0, res=0;
    	    for (int i=1; i<=len; i++)
    	    {
    	        int c=s[i]-'a', now=pos=t[pos].son[c];
    	        while (now && t[now].num!=-1)
    	        {
    	            res+=t[now].num; t[now].num=-1;
    	            now=t[now].fail;
    	        }
    	    }
    	    return res;
    	}
    	
    	void Build()
    	{
    		for (int i=1, n=read(); i<=n; i++) 
    			scanf("%s", s+1), insert(s);
    		build_AC();
    	}
    }
    

    Manacher

    const int N=11000005;
    char t[N], s[N<<1]; int p[N<<1];
    int main()
    {
    	scanf("%s", t+1); int n=strlen(t+1), ans=0;
    	for (int i=1; i<=n; i++) s[i<<1]=t[i], s[i<<1|1]='#';
    	(n<<=1)+=2; s[1]=s[n]='#';
    	for (int i=1, maxr=0, mid=0; i<=n; i++)
        {
            p[i]=(i<maxr)?min(p[2*mid-i], p[mid]+mid-i):1;
            while (i+p[i]<=n && s[i+p[i]]==s[i-p[i]]) p[i]++;
            if (p[i]+i>maxr) maxr=p[i]+i, mid=i;
        }
        for (int i=1; i<=n; i++) ans=max(ans, p[i]-1);
        printf("%d
    ", ans);
    	return 0;
    }
    

    最小表示法

    int main()
    {
    	int n=read(), k=0, i=0, j=1;
    	for (int i=0; i<n; i++) a[i]=read();
    	while (k<n && i<n && j<n)
    	{
    		if (a[(i+k)%n]==a[(j+k)%n]) k++;
    		else 
    		{
    			a[(i+k)%n]>a[(j+k)%n]?i=i+k+1:j=j+k+1;
    			i==j?i++:0; k=0;
    		}
    	} j=min(i, j);
    	for (int i=j; i<n; i++) printf("%d ", a[i]);
    	for (int i=0; i<j; i++) printf("%d ", a[i]); 
    }
    

    数学

    快速幂

    int Pow(int x, int t)
    {
        int res=1;
        while (t)
        {
            if (t&1) res=1ll*res*x%p;
            x=1ll*x*x%p; t>>=1;
        }
        return res;
    }
    

    逆元

    	inv[1]=1; for (int i=2; i<=n; i++) inv[i]=1ll*(p-p/i)*inv[p%i]%p;//线性求逆元
    	
    	int fac=1; for (int i=1; i<=n; i++) fac=1ll*fac*i%p;
    	ifac[n]=Pow(fac, p-2); for (int i=n-1; i; i--) ifac[i]=1ll*ifac[i+1]*(i+1)%p;//线性求阶乘逆元
    
    void Exgcd(int a, int b, int &x, int &y)
    {
    	if (!b) x=1, y=0;
    	else Exgcd(b, a%b, y, x), y-=a/b*x;
    }
    int inv(int a, int p)
    {
    	int x, y;
    	Exgcd(a, p, x, y);
    	return (x%p+p)%p;
    }//扩展欧几里得求逆元
    
    

    Lucas定理

    int C(int n, int m)
    {
    	if (n<m) return 0;
    	return (fac[n] * Pow(fac[m], p-2) % p) * Pow(fac[n-m], p-2) % p;
    }
    int Lucas(int n, int m, int p)
    {
    	if (!m) return 1;
    	return Lucas(n/p, m/p) * C(n%p, m%p) % p;
    }
    
    

    线性基

    for (int i=1; i<=n; i++)
    {
        int x=read();
        for (int j=max_log; ~j; j--) if (x>>j)
            {if (!p[j]) {p[j]=x; break;} else x^=p[j];}
    }
    for (int i=max_log; i>=0; i--) ans=max(ans, ans^p[i]);
    //Max_Xor_Sum
    

    线性筛素数

    void Euler_Prime(int n)
    {
    	memset(isprime, true, sizeof(isprime)); isprime[1]=0;
        int cnt=0;
        for (int i=2; i<=n; i++)
        {
            if (isprime[i]) prime[++cnt]=i;
            for (int j=1; j<=cnt && i*prime[j]<=n; j++)
            {
                isprime[i*prime[j]]=false;
                if (!(i%prime[j])) break;
            }
        }
    }
    
    void Get_Phi(int n)
    {
    	memset(isprime, true, sizeof(isprime)); isprime[1]=0;
        int cnt=0;
        for (int i=2; i<=n; i++)
        {
            if (isprime[i]) prime[++cnt]=i, phi[i]=i-1;
            for (int j=1; j<=cnt && i*prime[j]<=n; j++)
            {
                isprime[i*prime[j]]=0;
                if (!(i%prime[j])) {phi[i*prime[j]]=phi[i]*prime[j]; break;}
                	else phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
    
    void Get_Mu(int n)
    {
    	memset(isprime, true, sizeof(isprime)); isprime[1]=0; mu[1]=1;
        int cnt=0;
        for (int i=2; i<=n; i++)
        {
            if (isprime[i]) prime[++cnt]=i, mu[i]=-1;
            for (int j=1; j<=cnt && i*prime[j]<=n; j++)
            {
                isprime[i*prime[j]]=0;
                if (!(i%prime[j])) break;
                	else mu[i*prime[j]]=-mu[i];
            }
        }
    }
    

    矩阵快速幂

    struct Matrix
    {
    	int n, m; long long sq[N][N];
    	
    	Matrix(int _n, int _m){n=_n; m=_m; memset(sq, 0, sizeof(sq));}
    	
    	Matrix operator + (Matrix a)
    	{
    		Matrix ans(n, m);
    		for(int i=1; i<=n; i++) for(int j=1; j<=m; j++)
    			ans.sq[i][j]=(sq[i][j] + a.sq[i][j])%P;
    		return ans;
    	} 
    	
    	Matrix operator * (Matrix a)
    	{
    		Matrix ans(n, a.m);
    		for(int i=1; i<=n; i++) for(int j=1; j<=a.m; j++)
    		{
    			long long tmp=0;
    			for(int k=1; k<=m; k++)
    				tmp=(tmp+((long long)sq[i][k]*a.sq[k][j])%P)%P; 
    			ans.sq[i][j]=tmp;
    		}
    		return ans;
    	}
    };
    
    Matrix Pow (Matrix a, long long n)
    {
    	Matrix ans(a.n, a.n), tmp(a.n, a.n);
    	for(int i=1; i<=a.n; i++) ans.sq[i][i]=1;
    	memcpy(tmp.sq, a.sq, sizeof(tmp.sq));
    	while(n)
    	{
    		if(n&1) ans=ans*tmp;
    		n>>=1; tmp=tmp*tmp;
    	}
    	return ans;
    }
    

    拉格朗日插值

    int Lagrange(int *x, int *y, int n, int k)
    {
        int res=0;
        for (int i=1; i<=n; i++)
        {
            int s1=1, s2=1;
            for (int j=1; j<=n; j++) if (i^j)
            {
                s1=1ll*s1*(k-x[j])%P;
                s2=1ll*s2*(x[i]-x[j])%P;
            }
            res=(res+1ll*(1ll*s1*Pow(s2, P-2)%P)*y[i])%P;
        }
        return (res%P+P)%P;
    }//O(n^2)
    
    int Lagrange(int *y,int n,int k)
    {
    	int ans=0, fac=1; pre[0]=suf[n+1]=1; ifac[n]=Pow(fac, P-2);
    	for (int i=1; i<=n; i++) pre[i]=1ll*pre[i-1]*(k-i)%P;
    	for (int i=n; i; i--) suf[i]=1ll*suf[i+1]*(k-i)%P;
        for (int i=1; i<=n; i++) fac=1ll*fac*i%P;
        for (int i=n-1; i; i--) ifac[i]=1ll*ifac[i+1]*(i+1)%P;
    	for (int i=1; i<=n; i++)
    	{
    		int s1=1ll*pre[i-1]*suf[i+1]%P;
    		int s2=1ll*ifac[i-1]*ifac[n-i]%P;
    		ans=(ans+1ll*((n-i)&1?-1:1)*s1*s2%P*y[i])%P;
    	}
    	return (ans%P+P)%P;
    }//O(n)
    

    Miller Rabin

    #define int long long
    const int times=10;
    
    int mul(int x, int t, int P)
    {
    	int res=0;
    	for (; t; t>>=1, x=(x+x)%P) if (t&1) res=(res+x)%P;
    	return res;
    }
    
    int Pow(int x, int t, int P)
    {
    	int res=1;
    	for (; t; t>>=1, x=mul(x, x, P)) if (t&1) res=mul(res, x, P);
    	return res;
    }
    
    bool check(int a, int p)
    {
    	int x=p-1, k=0;
    	while (!(x&1)) x>>=1, k++;
    	x=Pow(a, x, p);
    	if (x==1) return true;
    	rep(i, 1, k)
    	{
    		if (x==p-1) return true;
    		x=mul(x, x, p);
    	}
    	return false;
    }
    
    bool Miller_Rabin(int x)
    {
    	if (x==2) return true; 
    	if (x<2) return false;
    	rep(i, 1, times) 
    	{
    		int a=rand()%(x-2)+2;
    		if (!check(a, x)) return false;
    	}
    	return true;
    }
    

    Pollard Rho

    #define int long long
    
    const int times=10;
    int max(int a, int b){return a>=b?a:b;}
    int sub(int a, int b){return a>=b?a-b:b-a;}
    int gcd(int a, int b){return b?gcd(b, a%b):a;}
    int mul(int x, int y, int P) 
    {
    	int t=(long double)x*y/P;
    	return ((x*y-t*P)%P+P)%P;
    }	
    int Pow(int x, int t, int P)
    {
    	int res=1;
    	for (; t; t>>=1, x=mul(x, x, P)) if (t&1) res=mul(res, x, P);
    	return res;
    }
    
    bool check(int a, int p)
    {
    	int x=p-1, k=0;
    	while (!(x&1)) x>>=1, k++;
    	x=Pow(a, x, p);
    	if (x==1) return true;
    	rep(i, 1, k)
    	{
    		if (x==p-1) return true;
    		x=mul(x, x, p);
    	}
    	return false;
    }
    
    bool Miller_Rabin(int x)
    {
    	if (x==2) return true; 
    	if (x<2) return false;
    	rep(i, 1, times) 
    	{
    		int a=rand()%(x-2)+2;
    		if (!check(a, x)) return false;
    	}
    	return true;
    }
    
    
    int solve(int n, int step, int add)
    {
    	if (!(n&1)) return 2;
    	int x=2, y=2, d=1;
    	while (1)
    	{
    		int tx=x, ty=y;
    		rep(i, 1, step)
    		{
    			x=mul(x, x, n)+add; if (x>=n) x-=n;
    			y=mul(y, y, n)+add; if (y>=n) y-=n;
    			y=mul(y, y, n)+add; if (y>=n) y-=n;
    			d=mul(d, sub(x, y), n);
    		}
    		d=gcd(n, d);
    		if (d==1) continue;
    		if (d^n) return d;
    		x=tx; y=ty;
    		rep(i, 1, step)
    		{
    			x=mul(x, x, n)+add; if (x>=n) x-=n;
    			y=mul(y, y, n)+add; if (y>=n) y-=n;
    			y=mul(y, y, n)+add; if (y>=n) y-=n;
    			d=gcd(n, sub(x, y));
    			if (d^1) return d%n;
    		}
    		return 0;
    	}
    }
    
    int Rho(int n)
    {
    	if (Miller_Rabin(n)) return n; 
    	int tmp=0, step=pow(n, 0.1), add=0;
    	while (!tmp) tmp=solve(n, step, ++add);
    	return max(Rho(tmp), Rho(n/tmp));
    }
    
    

    原根

    void Sieve(int MAX)
    {
    	for (int i=2; i<=MAX; i++)
    	{
    		if (!vis[i]) p[++cnt]=i;
    		for (int j=1; j<=cnt && p[j]*i<=MAX; j++)
    		{
    			vis[p[j]*i]=1;
    			if (!(i%p[j])) break;
    		}
    	}
    }
    
    int Pow(int x, int t)
    {
    	int res=1;
    	for (; t; t>>=1, x=1ll*x*x%P) if (t&1) res=1ll*res*x%P;
    	return res;
    }
    
    void GetFactor(int n)
    {
    	for (int i=1; i<=cnt; i++) 
    	{
    		if (n<p[i]*p[i]) return;
    		if (!(n%p[i])) fac[++tot]=p[i];
    	}
    }
    
    bool IsRoot(int n)
    {
    	for (int i=1; i<=tot; i++)
    		if (Pow(n, (P-1)/fac[i])==1) return false;
    	return true;
    }
    
    int GetRoot(int P);
    {
    	Sieve(31623); GetFactor(P-1);
    	for (int i=2; ; i++) if (IsRoot(i)) return i;
    }
    

    康托展开

    void Add(int x, int d){for (; x <= n; x += x & -x) t[x] += d;}
    int Query(int x)
    {
    	int res = 0;
    	for (; x; x -= x & -x) res += t[x];
    	return res;
    }
    
    int Cantor()
    {
    	n = read(); fac[0] = 1;
    	for (int i = 1; i <= n; ++i) p[i] = read();
    	for (int i = 1; i <= n; ++i) fac[i] = mul(fac[i - 1], i);
    	for (int i = 1; i <= n; ++i) Add(i, 1);
    	for (int i = 1; i <= n; ++i)
    	{
    		ans=add(ans, mul(sub(Query(p[i]), 1), fac[n - i]));
    		Add(p[i], -1);
    	}
    	return add(ans, 1);
    }
    

    图论

    最大流(Dinic)

    const int N = 500, M = 1000;
    struct node{int to, nxt, flow;}edge[M];
    int head[N], cur[N], dep[N], cnt, n, S, T;
    void pre(){memset(head, -1, sizeof(head)); cnt=-1;}
    
    void add(int u, int v, int w)
    {
        edge[++cnt] = (node){v, head[u], w};
        head[u] = cnt;
        
        edge[++cnt] = (node){u, head[v], 0};
        head[v] = cnt;
    }
    
    bool bfs()
    {
        memset(dep, 0, sizeof(dep)); 
    	dep[S] = 1;
    	
        queue<int> q; 
    	q.push(S);
    	
        memcpy(cur, head, sizeof(head));
        
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            for (int i = head[u]; ~i; i = edge[i].nxt)
            {
                int v = edge[i].to, f = edge[i].flow;
                if (f && !dep[v]) dep[v] = dep[u] + 1, q.push(v);
            }
        }
        
        return dep[T];
    }
    
    int dfs(int u, int lim)
    {
        if (!lim || u == T) return lim;
        
        int addflow = 0, flow;
        for (int i = cur[u]; ~i; i = edge[i].nxt)
        {
            cur[u] = i; 
    		int v = edge[i].to, f = edge[i].flow;
    		
            if (dep[v] == dep[u] + 1 && (flow = dfs(v, min(lim, f))))
            {
                addflow += flow; 
    			lim -= flow;
                edge[i].flow -= flow; 
    			edge[i ^ 1].flow += flow;
    			
                if (!lim) break;
            }
        }
        
        return addflow;
    }
    
    int Dinic()
    {
        int maxflow = 0;
        while (bfs()) 
    		maxflow += dfs(S, 1<<30);
        return maxflow;
    }
    
    
    

    费用流(EK&spfa)

    const int N=10005, M=1000005;
    struct node{int to, nxt, flow, cost;}edge[M];
    int head[N], flow[N], cost[N], pre[N], last[N], cnt;
    int vis[N], S, T;
    void prep(){memset(head, -1, sizeof(head)); cnt=-1;}
    
    void add(int u, int v, int f, int w)
    {
        edge[++cnt]=(node){v, head[u], f, w};
        head[u]=cnt;
        edge[++cnt]=(node){u, head[v], 0, -w};
        head[v]=cnt;
    }
    
    bool spfa()
    {
        memset(cost, 0x3f, sizeof(cost)); cost[S]=0;
        memset(flow, 0x3f, sizeof(flow));
        memset(vis, 0, sizeof(vis)); vis[S]=1;
        queue<int> q; q.push(S); pre[T]=-1;
        while (!q.empty())
        {
            int u=q.front(); q.pop();
            for (int i=head[u]; ~i; i=edge[i].nxt)
            {
                vis[u]=0; 
                int v=edge[i].to, w=edge[i].cost, f=edge[i].flow;
                if (f>0 && cost[u]+w<cost[v])
                {
                    cost[v]=cost[u]+w;
                    pre[v]=u; last[v]=i;
                    flow[v]=min(flow[u], f);
                    if (!vis[v]) vis[v]=1, q.push(v);
                }
            }
        }
        return ~pre[T];
    }
    
    int EK()
    {
        int maxflow=0, mincost=0;
        while (spfa())
        {
            maxflow+=flow[T]; mincost+=flow[T]*cost[T];
            int u=T;
            while (u^S)
            {
                edge[last[u]].flow-=flow[T];
                edge[last[u]^1].flow+=flow[T];
                u=pre[u];
            }
        }
        return mincost;
    }
    

    点分治(路径长为(K)的条数)

    inline void chkmax(int &x, int y){x<y?(x=y):0;}
    const int N=10005;
    vector<pair<int, int> > G[N];
    int size[N], Max[N], dis[N], vis[N];
    int sum, cnt, rt, n, m, K; long long ans;
    
    #define v i.first
    #define w i.second
    
    void GetRoot(int u, int fa)
    {
    	size[u]=1; Max[u]=0;
    	for (auto i: G[u]) if (v^fa && !vis[v])
    		GetRoot(v, u), chkmax(Max[u], size[v]), size[u]+=size[v];	
    	chkmax(Max[u], sum-size[u]);
    	if (Max[u]<Max[rt]) rt=u;
    }
    
    int LeftBound(int l, int x)
    {
    	int ans=0, r=cnt;
    	while (l<=r) 
    	{
    		int mid=l+r>>1;
    		if (dis[mid]<x) l=mid+1; 
    			else ans=mid, r=mid-1;
    	}
    	return ans;
    }
    
    int RightBound(int l, int x)
    {
    	int ans=0, r=cnt;
    	while (l<=r)
    	{
    		int mid=l+r>>1;
    		if (dis[mid]>x) r=mid-1;
    			else ans=mid, l=mid+1;
    	}
    	return ans;
    }
    
    void GetDis(int u, int fa, int Dis)
    {
    	for (auto i: G[u]) if (v^fa && !vis[v])
    		dis[++cnt]=Dis+w, GetDis(v, u, dis[cnt]);
    }
    
    int GetAns(int u, int Dis)
    {
    	dis[cnt=1]=Dis; GetDis(u, 0, Dis);
    	sort(dis+1, dis+cnt+1);
    	int l=1, ans=0;
    	while (l<cnt && dis[l]+dis[cnt]<K) l++;
    	while (l<cnt && (dis[l]<<1)<=K) 
    	{
    		int DisL=LeftBound(l+1, K-dis[l]);
    		int DisR=RightBound(l+1, K-dis[l]);
    		if (DisR>=DisL) ans+=DisR-DisL+1;
    		l++;
    	}
    	return ans;
    }
    
    void dfs(int u)
    {
    	vis[u]=1; ans+=GetAns(u, 0); 
    	for (auto i: G[u]) if (!vis[v])
    	{
    		ans-=GetAns(v, w); 
    		sum=size[v]; rt=0; GetRoot(v, u); dfs(rt);
    	} 
    }
    
    #undef v
    #undef w
    
    void add(int u, int v, int w)
    {
    	G[u].push_back(make_pair(v, w));
    	G[v].push_back(make_pair(u, w));
    }
    

    朱刘算法(最小树形图)

    const int N=105, M=10005, inf=0x3f3f3f3f;
    struct edge{int u, v, w;}E[M];
    int In_val[N], In_ver[N], vis[N], id[N], n, m, rt;
    
    int ZhuLiu()
    {
    	int ans = 0;
    	while (1)
    	{
    		memset(In_val, 0x3f, sizeof(In_val));
    		for (int i = 1; i <= m; ++i)
    		{
    			int u = E[i].u, v = E[i].v, w = E[i].w;
    			if (u ^ v && w < In_val[v]) In_val[v]=w, In_ver[v]=u;
    		}
    		for (int i = 1; i <= n; ++i) 
    			if (i ^ rt && In_val[i] == inf) return -1;
    		
    		int cnt = 0;
    		memset(vis, 0, sizeof(vis));
    		memset(id, 0, sizeof(id));
    		for (int i = 1; i <= n; ++i) if (i ^ rt)
    		{
    			int u = i; ans += In_val[u];
    			while (vis[u] ^ i && !id[u] && u ^ rt)
    				vis[u] = i, u = In_ver[u];
    			while (!id[u] && u ^ rt)
    			{
    				id[u] = ++cnt;
    				for (int v = In_ver[u]; v ^ u; v = In_ver[v]) id[v] = cnt;
    			}
    		}
    		if (!cnt) return ans;
    		
    		for (int i = 1; i <= n; ++i) if (!id[i]) id[i] = ++cnt;		
    		for (int i = 1; i <= m; ++i)
    		{
    			int u = E[i].u, v = E[i].v;
    			E[i].u = id[u]; E[i].v = id[v];
    			if (id[u] ^ id[v]) E[i].w -= In_val[v];
    		}
    		rt = id[rt]; n = cnt;
    	}
    }
    
    

    数据结构

    左偏树

    int Merge(int x, int y)
    {
    	if (!x || !y) return x|y;
    	if (a[x]<a[y] || (a[x]==a[y] && x>y)) swap(x, y);
    	rs[x]=Merge(rs[x], y);
    	if (dis[ls[x]]<dis[rs[x]]) swap(ls[x], rs[x]);
    	dis[x]=dis[rs[x]]+1;
    	return x;
    }
    
    int Delete(int x){return Merge(ls[x], rs[x]);}
    

    多项式

    FFT

    const double pi = acos(-1.0);
    
    namespace ComplexOperator
    {
        struct complex
        {
            double x, y;
            complex(double _x = 0.0, double _y = 0.0) 
    			{ x = _x; y = _y; }
        };
        complex operator + (complex a, complex b)
        {
            return complex(
    			a.x + b.x, 
    			a.y + b.y
    		);
        }
        complex operator - (complex a, complex b)
        {
            return complex(
    			a.x - b.x,
    			a.y - b.y
    		);
        }
        complex operator * (complex a, complex b)
        {
            return complex(
    			a.x * b.x - a.y * b.y,
    			a.x * b.y + a.y * b.x
    		);
        }
    }
    
    using namespace ComplexOperator;
    
    const int N = 4e6 + 5;
    
    complex a[N], b[N]; 
    int rev[N];
    
    void FFT(complex *a, int n, int x)
    {
        for (int i = 0; i < n; ++i) 
    		if (i < rev[i]) swap(a[i], a[rev[i]]);
    	
        for (int i = 1; i < n; i <<= 1)
        {
            complex Wn = complex(cos(pi / i), sin(pi / i) * x);
            for (int j = 0; j < n; j += (i << 1))
            {
                complex W = complex(1, 0);
                for (int k = 0; k < i; ++k, W = W * Wn)
                {
                    complex A1 = a[j + k];
    				complex A2 = W * a[i + j + k];
    				
                    a[j + k] = A1 + A2; 
    				a[i + j + k] = A1 - A2;
                }
            }
        }
    }
    
    void multiply(complex a[], complex b[], int n, int m)
    {
        int limit = 1, cnt = 0;
        while (limit <= n + m) limit <<= 1, ++cnt;
    	
        for (int i = 0; i < limit; ++i) 
    		rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (cnt - 1));
    	
        FFT(a, limit, 1); 
    	FFT(b, limit, 1);
        for (int i = 0; i <= limit; ++i) a[i] = a[i] * b[i];
        FFT(a, limit, -1);
        
        for (int i = 0; i <= n + m; ++i) a[i].x = (int)(a[i].x / limit + 0.5);
    }
    

    NTT

    const int N=4000005, P=998244353, G=3;
    inline int add(int x, int y){return x+y>=P?x+y-P:x+y;}
    inline int sub(int x, int y){return x-y<0?x-y+P:x-y;}
    inline int mul(int x, int y){return 1ll*x*y-1ll*x*y/P*P;}
    int a[N], b[N], rev[N];
    
    int Pow(int x, int t)
    {
    	int res=1;
    	for (; t; t>>=1, x=mul(x, x)) if (t&1) res=mul(res, x);
    	return res;
    }
    
    void NTT(int *a, int n, int x)
    {
    	for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i], a[rev[i]]);
    	for (int mid=1, len=2; mid<n; mid<<=1, len<<=1)
    	{
    		int Gn=Pow(G, (P-1)/len);
    		for (int i=0; i<n; i+=len)
    		{
    			int Gen=1;
    			for (int j=0; j<mid; j++, Gen=mul(Gen, Gn))
    			{
    				int A1=a[i+j], A2=mul(Gen, a[i+j+mid]);
    				a[i+j]=add(A1, A2); a[i+j+mid]=sub(A1, A2);
    			}
    		}
    	}
    	if (!~x) reverse(a+1, a+n);
    }
    
    void solve()
    {
    	int n=read(), m=read(), lim=1, cnt=0;
    	while (lim<=n+m) lim<<=1, cnt++;
    	rep(i, 0, n) a[i]=read();
    	rep(i, 0, m) b[i]=read();
    	rep(i, 0, lim) rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (cnt - 1));
    	NTT(a, lim, 1); NTT(b, lim, 1);
    	rep(i, 0, lim) a[i]=mul(a[i], b[i]);
    	NTT(a, lim, -1);
    	lim=Pow(lim, P-2);
    	rep(i, 0, n+m) printf("%d ", mul(a[i], lim));
    }
    
  • 相关阅读:
    .NET Tools...
    函数重载
    友元课后题
    怎么防止用户输入错误信息
    C#动态求圆的面积
    重载自增
    C++数学应用
    位运算符
    MSDN放出了VS2010简体中文正式版(附下载地址)
    字符串复制
  • 原文地址:https://www.cnblogs.com/ACMSN/p/10487023.html
Copyright © 2020-2023  润新知