模板

1.读入优化

inline int read()  
{  
    int ans=0,f=1;char t=getchar();  
    while(t<'0'||t>'9')   f=(t=='-'?-1:1),t=getchar();  
    while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();  
    return ans*f;  
}  
读入优化

2.并查集

#include<cstdio>
#include<cstring>
const int N=10010;
int fa[N];
inline int get(int x){if(fa[x]==x) return x;return fa[x]=get(fa[x]);} 
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) fa[i]=i;
    int flag,x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&flag,&x,&y);
        if(flag==1) fa[get(x)]=get(y);
        else{if(get(x)==get(y)) printf("Y\n");else printf("N\n");}
    }
    return 0;
}
并查集

3.最小生成树

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::sort;
using std::max;
const int N=200010;
struct node
{
    int v,u,p;
}e[N];
int fa[5050];
bool cmp(node a,node b){return a.p<b.p;}
int find(int x)
{
    if(x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x]; 
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d %d %d",&e[i].v,&e[i].u,&e[i].p);
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(e+1,e+1+m,cmp);
    int ans=0;
    for(int i=1;i<=m;i++)
    {
        int p=find(e[i].v),q=find(e[i].u);
        if(p!=q)
        {
//            printf("********\n");
            fa[p]=fa[q];
            ans+=e[i].p;
        }
    }
    printf("%d",ans);
    return 0;
}
最小生成树

4.字符串哈希

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::sort;
#define ull unsigned long long
const int N=10010;
const int M=1512;
char map[M];
ull sum[N],hash[M];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",map+1);
        memset(hash,0,sizeof(hash));
        int len=strlen(map+1);
        for(int j=1;j<=len;j++) hash[j]=hash[j-1]*31+(map[j-1]-'a'+1);
        sum[i]=hash[len];
    }
    int ans=1;
    sort(sum+1,sum+1+n);
    for(int i=2;i<=n;i++)
    {
        if(sum[i]!=sum[i-1]) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
字符串哈希

5.KMP字符串匹配

#include<cstdio>
#include<cstring>
const int N=1000010;
char a[N],b[N];
int lena,lenb,next[N];
void init()
{
    int j=0;next[1]=0;
    for(int i=2;i<=lenb;i++)
    {
        while(j&&b[j+1]!=b[i]) j=next[j];
        if(b[j+1]==b[i]) j++;
        next[i]=j;
    }
}
void sovle()
{
    int j=0;
    for(int i=1;i<=lena;i++)
    {
        while(j&&b[j+1]!=a[i]) j=next[j];
        if(b[j+1]==a[i]) j++;
        if(j==lenb) printf("%d\n",i-lenb+1);
    }
}
int main()
{
    scanf("%s %s",a+1,b+1);
    lena=strlen(a+1),lenb=strlen(b+1);
    init();
    sovle();
    for(int i=1;i<=lenb;i++) printf("%d ",next[i]);
    return 0;
}
KMP字符串匹配

6.堆

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    int n;
    scanf("%d",&n);
    int pd;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&pd);
        if(pd==1) 
        {
            int v;
            scanf("%d",&v);
            q.push(v);
        }
        if(pd==2)
        {
            printf("%d\n",q.top());
        }
        if(pd==3)
        {
            q.pop();
        }
    }
    return 0;
}

7.矩阵快速幂

#include<cstdio>
#include<cstring>
const long long N=112;
long long res[N][N],tt[N][N];
long long n,m;
const long long mod=1e9+7;  
inline void matrix(long long a[N][N],long long b[N][N])
{
    memset(tt,0,sizeof(tt));
    for(long long i=1;i<=n;i++)
    for(long long j=1;j<=n;j++)
    for(long long k=1;k<=n;k++)
    tt[i][j]=( tt[i][j]+(long long)a[i][k]*b[k][j]%mod)%mod;
    for(long long i=1;i<=n;i++)
    for(long long j=1;j<=n;j++)
    a[i][j]=tt[i][j];    
}
long long a[N][N];
void j_poww(long long b)
{
    for(long long i=1;i<=n;i++)
    for(long long j=1;j<=n;j++)
    scanf("%lld",&a[i][j]);
    memset(res,0,sizeof(res));
    for(long long i=1;i<=n;i++) res[i][i]=1;
    while(b)
    {
        if(b&1) matrix(res,a);
        b>>=1;    
        matrix(a,a);
    }
}
int main()
{
    scanf("%lld %lld",&n,&m);
    j_poww(m);
    for(long long i=1;i<=n;i++,printf("\n"))
    for(long long j=1;j<=n;j++)
    printf("%lld ",res[i][j]);    
    return 0;
}
矩阵快速幂

 8.线性筛素数

#include<cstdio>
#include<cstring>
const int N=1e7+12;
int prime[N],book[N];
int main()
{
    int n;
    scanf("%d",&n);
    int tot=0;
    for(int i=2;i<=n;i++)
    {
        if(!book[i]) prime[++tot]=i;
        for(int j=1;j<=tot;j++)
        {
            if(i*prime[j]>n) break;
            book[i*prime[j]]=1;
            if(!i%prime[j]) break;
        }
    }
    for(int i=1;i<=tot;i++) printf("%d ",prime[i]);
    return 0; 
}
线性筛素数

 9.卢卡斯定理

#include<cstdio>
#include<cstring>
#define ll long long
const int N=1e6+12;
ll aa[N<<1];
ll p;
inline ll max(ll a,ll b){if(a>=b)return a;return b;}
inline ll poww(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        b>>=1;a=a*a%p;
    }
    return ans;
}
ll C(ll n,ll m){
    if(n<m) return 0;
    if(n<p) return aa[n]*poww(aa[m],p-2)%p*poww(aa[n-m],p-2)%p;
    return C(n/p,m/p)*C(n%p,m%p)%p;
} 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll n,m;
        scanf("%lld %lld %lld",&n,&m,&p);
        memset(aa,0,sizeof(aa));
        aa[0]=1;
        for(int i=1;i<=n+m;i++) aa[i]=aa[i-1]*i%p;
        ll ans=C(n+m,n);
        printf("%lld\n",ans);
    }
    return 0;
}
//C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
//C(m,m+n)
卢卡斯定理

10.线性求逆元

#include<cstdio>
#include<cstring>
#define ll long long 
const int N=3e6+12;
ll inv[N];
int main()
{
    int n,p;
    scanf("%d %d",&n,&p);
    inv[1]=1;
    printf("1\n");
    for(int i=2;i<=n;i++)
        inv[i]=(-(p/i)*inv[p%i])%p+p,printf("%lld\n",inv[i]);
    return 0;
}
线性求逆元

11.ST表

#include<cstdio>
#include<cstring> 
const int N=1e5+12;
int map[N];
int lg[N],f[N][27];
inline int max(int a,int b){if(a>=b) return a;return b;}
inline int query(int l,int r)
{
    int t=lg[r-l+1];
    return max(f[l][t],f[r-(1<<t)+1][t]);
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&map[i]);
    for(int i=1;i<=n;i++) f[i][0]=map[i];
    for(int j=1;j<=21;j++)
    for(int i=1;i<=n-(1<<j-1);i++)
    f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
    lg[1]=0;
    for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
    int l,r;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&l,&r);
        printf("%d\n",query(l,r));
    }
    return 0;
}
ST表

 12.文件(freopen,fclose)

#include<cstdio>
int main()
{
    freopen("div.in","r",stdin);
    freopen("div.out","w",stdout);


    fclose(stdin);
    fclose(stdout);
    return 0;
}
freopen,fclose

 13.匈牙利算法

#include<cstdio>
#include<cstring>
const int N=210;
int map[N][N];
int book[N];
int tag[N];
int n,m;
bool find(int x)
{
    for(int i=1;i<=m;i++)
    {
        if(map[x][i]&&(!book[i]))
        {
            book[i]=1;
            if(!tag[i]||find(tag[i]))
            {
                tag[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    
    scanf("%d %d",&n,&m);
    int p;
    for(int i=1;i<=n;i++)
    {        
        while(true)
        {
            scanf("%d",&p);
            if(!p) break;
            else map[i][p]=1;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(book,0,sizeof(book));
        if(find(i)) ans++;
    }
    printf("%d",ans);
    return 0;
}
匈牙利算法

14.强联通分量

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::min;
const int N=100010; 
struct node{int next,to,from;}e[N];
int first[N];
int book[N];
int dfn[N],low[N],stack[N],cd[N];
int cnt=0;
void insert(int v,int u)
{
    e[++cnt].to=u;e[cnt].from=v;e[cnt].next=first[v];first[v]=cnt;
}
int tot=0,top=0,num=0;
int size[N],color[N];
void tarjan(int x)
{
    dfn[x]=low[x]=++tot;
    book[x]=1;stack[++top]=x;
    for(int i=first[x];i;i=e[i].next)
    {
        if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]);
        else if(book[e[i].to])    low[x]=min(low[x],low[e[i].to]);
    }
    if(dfn[x]==low[x])
    {
        ++num;
        while(stack[top]!=x)
        {
            book[stack[top]]=0;
            color[stack[top]]=num;
            size[num]++;
            top--;
        }
        book[x]=0;
        color[x]=num;
        size[num]++;
        top--;
    }
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int v,u;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&v,&u);
        insert(v,u);
    }
    int ans=0;
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=num;i++) if(size[i]!=1) ans++;    
    cnt=0;
    memset(first,0,sizeof(first));
    for(int i=1;i<=m;i++) 
    if(color[e[i].from]!=color[e[i].to]) cd[color[e[i].from]]++,insert(color[e[i].from],color[e[i].to]);
    ans=0;
    int aim;
    for(int i=1;i<=num;i++) if(!cd[i]) ans++,aim=i;
    if(ans!=1) printf("0");
    else printf("%d\n",size[aim]);
    return 0;
}
强联通分量

 15.多重背包

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
const int N=217;
int v[N],w[N],m[N];
int dp[200010];
int main()
{
    int nv,n;
    scanf("%d %d",&n,&nv);
    for(int i=1;i<=n;i++)        
    {
        scanf("%d %d %d",&v[i],&w[i],&m[i]);
    }
    for(int i=1;i<=n;i++)
    {
        if(m[i]==1)
        {
            for(int j=nv;j>=v[i];j--)
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
        else if(m[i]>=1)
        {
            if(v[i]*m[i]>=nv)
            {
                for(int j=v[i];j<=nv;j++)
                    dp[j]=max(dp[j],dp[j-v[j]]+w[i]);
            }
            else 
            {
                int k=1;
                while(k<m[i])
                {
                    for(int j=nv;j>=v[i]*k;j--)
                        dp[j]=max(dp[j],dp[j-v[i]*k]+w[i]*k);
                    m[i]-=k;
                    k<<=1;
                }
                if(m[i]>0) 
                    for(int j=nv;j>=v[i]*m[i];j--)
                        dp[j]=max(dp[j],dp[j-v[i]*m[i]]+w[i]*m[i]);
            }
        }
        else 
        {
            for(int j=v[i];j<=nv;j++)
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
    }
    printf("%d",dp[nv]);
    return 0;
}
多重背包

16.拓扑排序

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=200010;
struct node
{
    int to,next;
}e[N];
int first[N];
int in[N];
int cnt=0;
int ans[N];
priority_queue<int>q;
inline void insert(int u,int v)
{
    e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int v,u;
    int tot=n+1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&v,&u);
        insert(u,v);in[v]++;
    }
    for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
    while(!q.empty())
    {
        int p=q.top();q.pop();
        ans[p]=--tot;
        for(int i=first[p];i;i=e[i].next)
        {
            --in[e[i].to];
            if(!in[e[i].to]) q.push(e[i].to);
        }
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    return 0;
}
拓扑排序

 

posted @ 2017-11-07 13:20  12fs  阅读(205)  评论(0编辑  收藏  举报