Template.

Background

还有一个礼拜就省选了,连板子都不会打的Zars19觉得应该来一次模板补全计划。

(尽管好多该学的东西还没学)

Update:省选已经完了…但是还没补全

1.0 树链剖分(BZOJ1036 [ZJOI2008]树的统计Count)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define INF 0x3f3f3f3f
#define MAXN 30005
using namespace std;
int n,q,sz=0,head[MAXN],w[MAXN],ans;
int dep[MAXN],top[MAXN],pos[MAXN],num[MAXN],father[MAXN],siz[MAXN],cnt=0;
struct Node1
{
    int next,to;
}Edges[MAXN*2];
void addedge(int u,int v)
{
    Edges[++cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
}
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
void dfs1(int u)
{
    siz[u]=1;
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(v==father[u])continue;
        father[v]=u,dep[v]=dep[u]+1;
        dfs1(v);
        siz[u]+=siz[v];
    }
}
void dfs2(int u,int t)
{
    sz++,pos[u]=sz,num[sz]=u;
    int maxv=0,k=0;
    top[u]=t;
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(v==father[u])continue;
        if(siz[v]>maxv)maxv=siz[v],k=v;
    }
    if(k)dfs2(k,t);
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(v==father[u]||v==k)continue;
        dfs2(v,v);
    }
}
struct Node2
{
    int l,r,sum,maxn;
}t[MAXN*4];
void build(int idx,int l,int r)
{
    t[idx].l=l,t[idx].r=r;
    if(l==r)
    {
        t[idx].sum=t[idx].maxn=w[num[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(idx<<1,l,mid);
    build(idx<<1|1,mid+1,r);
    t[idx].maxn=max(t[idx<<1].maxn,t[idx<<1|1].maxn);
    t[idx].sum=t[idx<<1].sum+t[idx<<1|1].sum;
}
int query1(int idx,int a,int b)
{
    if(a<=t[idx].l&&b>=t[idx].r)
    return t[idx].maxn;
    int mid=(t[idx].l+t[idx].r)>>1;
    if(b<=mid)return query1(idx<<1,a,b);
    if(a>mid)return query1(idx<<1|1,a,b);
    return max(query1(idx<<1,a,b),query1(idx<<1|1,a,b));
}
int query2(int idx,int a,int b)
{
    if(a<=t[idx].l&&b>=t[idx].r)
    return t[idx].sum;
    int mid=(t[idx].l+t[idx].r)>>1;
    if(b<=mid)return query2(idx<<1,a,b);
    if(a>mid)return query2(idx<<1|1,a,b);
    return query2(idx<<1,a,b)+query2(idx<<1|1,a,b);
}
void change(int idx,int a,int b)
{
    if(t[idx].l==t[idx].r){t[idx].maxn=t[idx].sum=b;return;}
    int mid=(t[idx].l+t[idx].r)>>1;
    if(a<=mid)change(idx<<1,a,b);
    else change(idx<<1|1,a,b);
    t[idx].maxn=max(t[idx<<1].maxn,t[idx<<1|1].maxn);
    t[idx].sum=t[idx<<1].sum+t[idx<<1|1].sum;
}
void QMAX(int a,int b)
{
    ans=-INF;
    while(top[a]!=top[b])
    {
        if(dep[top[a]]<dep[top[b]])swap(a,b);
        ans=max(ans,query1(1,pos[top[a]],pos[a]));
        a=father[top[a]];
    }
    if(pos[a]>pos[b])swap(a,b);
    ans=max(ans,query1(1,pos[a],pos[b]));
    printf("%d\n",ans);
}
void QSUM(int a,int b)
{
    ans=0;
    while(top[a]!=top[b])
    {
        if(dep[top[a]]<dep[top[b]])swap(a,b);
        ans+=query2(1,pos[top[a]],pos[a]);
        a=father[top[a]];
    }
    if(pos[a]>pos[b])swap(a,b);
    ans+=query2(1,pos[a],pos[b]);
    printf("%d\n",ans);
} 
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<n;i++)
    {
        int a=read(),b=read();
        addedge(a,b);
        addedge(b,a);
    }
    for(int i=1;i<=n;i++)
    w[i]=read();
    dfs1(1);dfs2(1,1);
    build(1,1,sz);
    q=read();
    char opt[10];int a,b;
    for(int i=1;i<=q;i++)
    {
        scanf("%s",opt);
        a=read(),b=read();
        if(!strcmp(opt,"CHANGE"))
        change(1,pos[a],b);
        else if(!strcmp(opt,"QMAX"))
        QMAX(a,b);
        else 
        QSUM(a,b);
    }
    return 0;
} 
View Code

2.0 Tarjan离线LCA

2.1 倍增LCA

3.0 点分治(BZOJ2152 聪聪可可)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define MAXN 20005
#define INF 0x3f3f3f3f
using namespace std;
int n,head[MAXN],siz[MAXN],maxv[MAXN],root=0,tot=0,num=0,cnt=0,t[3],p,q;
bool vis[MAXN];
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct Node
{
    int next,to,w;
}Edges[MAXN*2];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
void addedge(int u,int v,int w)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
    Edges[cnt++].w=w;
}
void getroot(int u,int f)
{
    siz[u]=1,maxv[u]=0;
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(v==f||vis[v])continue;
        getroot(v,u);
        siz[u]+=siz[v],maxv[u]=max(maxv[u],siz[v]);
    }
    maxv[u]=max(maxv[u],tot-siz[u]);
    if(maxv[u]<maxv[root])root=u;
}
void getdeep(int u,int f,int d)
{
     t[d]++;
     for(int i=head[u];~i;i=Edges[i].next)
     {
         int v=Edges[i].to;
         if(v==f||vis[v])continue;
         getdeep(v,u,(d+Edges[i].w)%3);
     }
}
int calc(int u,int d)
{
    memset(t,0,sizeof(t));
    getdeep(u,0,d);
    return t[0]*t[0]+t[1]*t[2]*2;
}
void work(int u)
{
    vis[u]=1;p+=calc(u,0);
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(vis[v])continue;
        p-=calc(v,Edges[i].w%3);
        tot=siz[v],root=0;
        getroot(v,u),work(root);
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read(),w=read();
        addedge(u,v,w),addedge(v,u,w);
    }
    maxv[0]=INF,tot=n;
    p=0,q=n*n;
    getroot(1,0),work(1);
    int t=gcd(p,q);
    printf("%d/%d\n",p/t,q/t);
    return 0;
}
View Code

数据结构

1.0 splay(BZOJ3223 Tyvj 1729 文艺平衡树)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,a[100005],root,siz=0;
struct Node{
    int ch[2],father,val,rev,siz;
}t[100005];
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
void Update(int x)
{
    t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+1;
}
void Pushdown(int x)
{
    if(t[x].rev)
    {
        t[x].rev=0;
        if(t[x].ch[0])t[t[x].ch[0]].rev^=1;
        if(t[x].ch[1])t[t[x].ch[1]].rev^=1;
        swap(t[x].ch[0],t[x].ch[1]);
    }
}
void Rotate(int x,int &k)
{
    Pushdown(x);
    int y=t[x].father,z=t[y].father;
    int p=(t[y].ch[0]==x)?0:1;
    if(y!=k)
    {
        if(t[z].ch[0]==y)t[z].ch[0]=x;
        else t[z].ch[1]=x;
    }
    else k=x;
    t[x].father=z;
    t[y].ch[p]=t[x].ch[p^1];
    t[t[x].ch[p^1]].father=y;
    t[x].ch[p^1]=y;
    t[y].father=x;
    Update(y),Update(x);
}
void Splay(int x,int &k)
{
    while(x!=k)
    {
        int y=t[x].father,z=t[y].father;
        if(y!=k)
        {
            if((t[y].ch[0]==x)^(t[z].ch[0]==y))
            Rotate(x,k);
            else Rotate(y,k);
        }
        Rotate(x,k);
    }
}
int Build(int l,int r,int f)
{
    if(l>r)return 0;
    int mid=(l+r)>>1,now=++siz;
    t[now].father=f;
    t[now].rev=0;
    t[now].val=mid;
    t[now].ch[0]=Build(l,mid-1,now);
    t[now].ch[1]=Build(mid+1,r,now);
    Update(now);
    return now;
}
int Find(int x,int k)
{
    if(!k)return 0;
    Pushdown(x);
    if(t[t[x].ch[0]].siz>=k)return Find(t[x].ch[0],k);
    else if(t[t[x].ch[0]].siz+1<k)return Find(t[x].ch[1],k-t[t[x].ch[0]].siz-1);
    return x;
}
void Print(int k)
{
    if(!k)return;
    Pushdown(k);
    Print(t[k].ch[0]);
    if(t[k].val!=0&&t[k].val!=n+1)
    printf("%d ",t[k].val);
    Print(t[k].ch[1]);
} 
int main()
{
    n=read(),m=read();
    root=Build(0,n+1,0);
    for(int i=1;i<=m;i++)
    {
        int l,r;
        l=read(),r=read();
        int x=Find(root,l),y=Find(root,r+2);
        Splay(x,root);Splay(y,t[root].ch[1]);
        t[t[y].ch[0]].rev^=1;
    }Print(root);
    return 0;
}
View Code

1.1 treap(BZOJ3224 TYVJ 1728 普通平衡树)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
using namespace std;
int n,siz=0,root=0,ans;
struct Node
{
    int lch,rch,val,siz,w,rank;
}t[100005];
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar(); 
    }
    return x*f;
}
void update(int k)
{
    t[k].siz=t[t[k].lch].siz+t[t[k].rch].siz+t[k].w;
}
void leftRotate(int &k)
{
    int p=t[k].rch;
    t[k].rch=t[p].lch;
    t[p].lch=k;
    t[p].siz=t[k].siz;
    update(k);k=p;
}
void rightRotate(int &k)
{
    int p=t[k].lch;
    t[k].lch=t[p].rch;
    t[p].rch=k;
    t[p].siz=t[k].siz;
    update(k);k=p;
}
void Insert(int &k,int x)
{
    if(!k){
        siz++;k=siz;
        t[k].siz=t[k].w=1;
        t[k].val=x;
        t[k].rank=rand();
        return;
    }
    t[k].siz++;
    if(t[k].val==x)
    {t[k].w++;return;}
    if(x<t[k].val){
        Insert(t[k].lch,x);
        if(t[t[k].lch].rank<t[k].rank)rightRotate(k);
        return;
    }
    else{
        Insert(t[k].rch,x);
        if(t[t[k].rch].rank<t[k].rank)leftRotate(k);
        return;
    }
}
void Delete(int &k,int x)
{
    if(!k)return;
    if(t[k].val==x)
    {
        if(t[k].w>1)
        {t[k].siz--;t[k].w--;return;}
        if(!t[k].lch||!t[k].rch)
        {k=t[k].lch+t[k].rch;return;}
        if(t[t[k].lch].rank>t[t[k].rch].rank){
            leftRotate(k);Delete(k,x);
            return;
        }
        else{
            rightRotate(k);Delete(k,x);
            return;
        }
    }
    t[k].siz--;
    if(x<t[k].val){
        Delete(t[k].lch,x);
        return;
    }
    else{
        Delete(t[k].rch,x);
        return;
    }
}
int queryRank(int k,int x)
{
    if(!k)return 0;
    if(x==t[k].val)return t[t[k].lch].siz+1;
    else if(x<t[k].val)return queryRank(t[k].lch,x);
    else return t[t[k].lch].siz+t[k].w+queryRank(t[k].rch,x);
}
int queryNum(int k,int x)
{
    if(!k)return 0;
    if(x<=t[t[k].lch].siz)return queryNum(t[k].lch,x);
    else if(x>t[t[k].lch].siz+t[k].w)return queryNum(t[k].rch,x-t[t[k].lch].siz-t[k].w);
    else return t[k].val;
}
void queryPre(int k,int x)
{
    if(!k)return;
    if(x<=t[k].val)queryPre(t[k].lch,x);
    else {ans=t[k].val,queryPre(t[k].rch,x);}
}
void querySuc(int k,int x)
{
    if(!k)return;
    if(x>=t[k].val)querySuc(t[k].rch,x);
    else {ans=t[k].val,querySuc(t[k].lch,x);}
}
int main()
{
    srand(time(0));
    n=read();
    for(int i=1;i<=n;i++)
    {
        int opt,x;
        opt=read(),x=read();
        switch(opt)
        {
            case 1:Insert(root,x);break;
            case 2:Delete(root,x);break;
            case 3:printf("%d\n",queryRank(root,x));break;
            case 4:printf("%d\n",queryNum(root,x));break;
            case 5:ans=0;queryPre(root,x);printf("%d\n",ans);break;
            case 6:ans=0;querySuc(root,x);printf("%d\n",ans);break;
        }
    }
    return 0;
}
View Code

图论

1.0 强连通分量

void tarjan(int u)
{
    dfn[u]=low[u]=++dfn_clock;
    vis[u]=ins[u]=1;s.push(u);
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(!vis[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(ins[v])
        {low[u]=min(low[u],dfn[v]);}
    }
    if(dfn[u]==low[u])
    {
        tot++;int t=-1;
        while(t!=u)
        {
            t=s.top();
            sccno[t]=tot;
            ins[t]=0;
            s.pop();
        }
    }
}
View Code

1.1 割点

1.2 割边

2.0 Dinic (草地排水)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN 250
using namespace std;
int m,n,s,t,level[MAXN],head[MAXN],cnt=0;
struct Node{
    int next,to,cap;
}Edges[MAXN*2];
void addedge(int u,int v,int c)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
    Edges[cnt++].cap=c;
}
void insert(int u,int v,int c){
    addedge(u,v,c);
    addedge(v,u,0);
}
bool bfs()
{
    memset(level,-1,sizeof(level));
    level[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=Edges[i].next)
        {
            int v=Edges[i].to;
            if(level[v]==-1&&Edges[i].cap)
            level[v]=level[u]+1,q.push(v);
        }
    }
    if(level[t]==-1)return false;
    return true;
}
int dfs(int u,int flow)
{
    int f=0,d=0;
    if(u==t)return flow;
    for(int i=head[u];~i&&flow>f;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(level[v]==level[u]+1&&Edges[i].cap)
        {
            d=dfs(v,min(flow-f,Edges[i].cap));
            f+=d;
            Edges[i].cap-=d;
            Edges[i^1].cap+=d;
        }
    }
    if(!f)level[u]=-1;
    return f;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&m,&n);
    s=1,t=n;
    for(int i=1;i<=m;i++)
    {
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        insert(u,v,c);
    }
    int ans=0,d;
    while(bfs())
    {
        while(d=dfs(s,INF))
        ans+=d;
    }
    printf("%d",ans);
    return 0;
} 
View Code

2.1 费用流

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
int m,n,s,t,a[450],pre[450],dis[450],head[450],cnt=0,MF,MC;
bool inq[450];
struct Node{
    int next,from,to,cap,w;
}Edges[30005];
void addedge(int u,int v,int c,int w)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].from=u;
    Edges[cnt].to=v;
    Edges[cnt].cap=c;
    Edges[cnt++].w=w;
}
void insert(int u,int v,int c,int w){
    addedge(u,v,c,w);
    addedge(v,u,0,-w);
}
void MCMF()
{
    MF,MC=0;
    while(1)
    {
        memset(dis,0x3f,sizeof(dis));
        memset(a,0,sizeof(a));
        int f=0;
        queue<int>q;
        q.push(s);
        inq[s]=1,a[s]=INF,dis[s]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();inq[u]=0;
            for(int i=head[u];~i;i=Edges[i].next)
            {
                int v=Edges[i].to;
                if(dis[u]+Edges[i].w<dis[v]&&Edges[i].cap>0)
                {
                    dis[v]=dis[u]+Edges[i].w;
                    a[v]=min(a[u],Edges[i].cap);
                    pre[v]=i;
                    if(!inq[v]){q.push(v);inq[v]=1;}
                }
            }
        }
        if(a[t]==0)break;
        int p=t;
        MC+=a[t]*dis[t];
        while(p!=s){
            Edges[pre[p]].cap-=a[t];
            Edges[pre[p]^1].cap+=a[t];
            p=Edges[pre[p]].from;
        }
        MF+=a[t];
        
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    s=1,t=n;
    for(int i=1;i<=m;i++)
    {
        int u,v,c,w;
        scanf("%d%d%d%d",&u,&v,&c,&w);
        insert(u,v,c,w);
    }
    MCMF();
    printf("%d %d\n",MF,MC);
    return 0;
} 
View Code

3.0 匈牙利算法(UOJ#78. 二分图最大匹配)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int n1,n2,m,head[505],cnt=0,ans=0,link[505];
bool vis[505];
struct Node
{
    int next,to;
}Edges[250005];
void addedge(int u,int v)
{
    Edges[++cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].to=v;
}
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
bool dfs(int u)
{
    for(int i=head[u];~i;i=Edges[i].next)
    {
        int v=Edges[i].to;
        if(!vis[v])
        {
            vis[v]=1;
            if(!link[v]||dfs(link[v]))
            {link[v]=u;return true;}
        }
    }
    return false;
}
int main()
{
    memset(head,-1,sizeof(head));
    n1=read(),n2=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        int v=read(),u=read();
        addedge(u,v);
    }
    for(int i=1;i<=n2;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;
    }
    printf("%d\n",ans);
    for(int i=1;i<=n1;i++)
    printf("%d ",link[i]);
    return 0;
} 
View Code

字符串

1.0 KMP

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define MAXN 1000005
using namespace std;
int n,m,next[MAXN],cnt=0;
char a[MAXN],b[MAXN];
int main()
{
    scanf("%s%s",a+1,b+1);
    n=strlen(a+1),m=strlen(b+1);
    int j=0;next[1]=0;
    for(int i=2;i<=m;i++)
    {
        while(j!=0&&b[i]!=b[j+1])j=next[j];
        if(b[i]==b[j+1])j++;
        next[i]=j;
    }
    j=0;
    for(int i=1;i<=n;i++)
    {
        while(j!=0&&a[i]!=b[j+1])j=next[j];
        if(a[i]==b[j+1])j++;
        if(j==m){j=next[j],++cnt;}
    }
    printf("%d\n",cnt);
    return 0;
}
View Code

2.0 AC自动机(BZOJ3172 TJOI2013 单词)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,siz,root,q[1000010],head,tail,pos[202];
char word[1000010];
struct Node{
    int next[26],cnt,fail;
    bool vis;
}trie[1000010];
int newnode()
{
    siz++;
    trie[siz].cnt=trie[siz].fail=trie[siz].vis=0;
    memset(trie[siz].next,0,sizeof(trie[siz].next));
    return siz;
}
void insert(int x,char* word)
{
    int i=0,p=root;
    while(word[i])
    {
        int idx=word[i]-'a';
        if(!trie[p].next[idx])trie[p].next[idx]=newnode();
        p=trie[p].next[idx];
        trie[p].cnt++;
        i++;
    }
    pos[x]=p;
}
void build()
{
    head=0,tail=0;
    q[++tail]=root;
    while(head<tail)
    {
        int p=q[++head];
        for(int i=0;i<26;i++)
        {
            int t=trie[p].fail;
            while(t&&!trie[t].next[i])t=trie[t].fail;
            if(trie[p].next[i])
            {
                trie[trie[p].next[i]].fail=t?trie[t].next[i]:root;
                q[++tail]=trie[p].next[i];
            }
            else trie[p].next[i]=t?trie[t].next[i]:root;
        }
    }
}
void work()
{
    int res=0;
    for(int p=tail;p>0;p--)
    {
        int t=trie[q[p]].fail;
        trie[t].cnt+=trie[q[p]].cnt;
    }
    for(int i=1;i<=n;i++)
    printf("%d\n",trie[pos[i]].cnt);
}
int main()
{
    scanf("%d",&n);
    siz=0,root=newnode();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",word);
        insert(i,word);
    }
    build();work();
    return 0;
}
View Code

3.0 Manachar

4.0 SAM

5.0 SA

计算几何

1.0 点和直线

int dcmp(double x){        //实数比较 
    if(fabs(x)<EPS)return 0;
    return x>0?1:-1;
}
struct Point{        //点\向量的定义 
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
    Point operator + (Point A){return Point(x+A.x,y+A.y);}
    Point operator - (Point A){return Point(x-A.x,y-A.y);}
    Point operator * (double p){return Point(x*p,y*p);}
    Point operator / (double p){return Point(x/p,x/p);}    
    bool operator == (Point A){return dcmp(x-A.x)==0&&dcmp(y-A.y)==0;}
};
typedef Point Vector;
double dot(Vector A,Vector B){        //点积 
    return A.x*B.x+A.y*B.y;
}
double cross(Vector A,Vector B){    //叉积 
    return A.x*B.y-B.x*A.y;
}
double length(Vector A){        //向量的长度 
    return sqrt(dot(A,A));
}
double angle(Vector A,Vector B){        //两向量的转角 
    return acos(dot(A,B)/length(A)/length(B));
}
Vector rotate(Vector A,double rad){        //向量的旋转 
    return Vector(cos(rad)*A.x-sin(rad)*A.y,sin(rad)*A.x+cos(rad)*A.y);
}
Vector normal(Vector A){        //法向量 
    double l=length(A);
    return Vector(-A.y/l,A.x/l);
}
struct Line{        //线 
    Point p;Vector v;
    Line(Point p=Point(0,0),Vector v=Vector(0,0)):p(p),v(v){}
};
Point get_intersection(Line A,Line B){        //两直线求交 
    Point u=A.p-B.p;
    double t=cross(B.v,u)/cross(A.v,B.v);
    return A.p+A.v*t;
}
double dis_line(Point P,Point A,Point B){        //点到直线的距离 
    Vector v1=B-A,v2=P-A;
    return fabs(cross(v1,v2)/length(v1));
}
double dis_segment(Point P,Point A,Point B){        //点到线段的距离 
    Vector v1=B-A,v2=P-A,v3=P-B;
    if(dcmp(dot(v1,v2)<0))return length(v2);
    if(dcmp(dot(v1,v3)>0))return length(v3); 
    return fabs(cross(v1,v2)/length(v1));
}
Point get_projection(Point P,Point A,Point B){        //点在直线上的投影 
    Vector v=B-A; 
    return A+v*(dot(P-A,v)/dot(v,v)); 
} 
bool segment_properintersection(Point a1,Point a2,Point b1,Point b2)    //线段相交判定 
{
    double c1=cross(b2-b1,a1-b1),c2=cross(b2-b1,a2-b1),
    c3=cross(a2-a1,b1-a1),c4=cross(a2-a1,b2-a1);
    return dcmp(c1)*dcmp(c2)<=0&&dcmp(c3)*dcmp(c4)<=0;
}
View Code

2.0 圆

struct Circle{
    Point c;double r;
    Point getpoint(double ang){        //获取圆上弧度角为ang的点 
        return Point(c.x+r*cos(ang),c.y+r*sin(ang));
    }
};
int getLineCircle_intersection(Line L,Circle C,double& t1,double& t2,vector<Point>& sol){
    double a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y;        //直线与圆的交点 
    double e=a*a+c*c,f=2*a*b+2*c*d,g=b*b+d*d-C.r*C.r;
    double delta=(f*f)-4*e*g;
    if(dcmp(delta)<0)return 0;
    if(!dcmp(delta)){
        t1=-f/(2*e);sol.push_back(L.p+L.v*t1);
        return 1;
    }
    t1=-f+sqrt(delta)/(2*e);t2=-f-sqrt(delta)/(2*e);
    sol.push_back(L.p+L.v*t1);sol.push_back(L.p+L.v*t2);
    return 2;
}
double angle(Vector A){        //极角 
    return atan2(A.y,A.x);
}
int getCircleCircle_intersection(Circle C1,Circle C2,vector<Point>& sol){        
    double d=length(C1.c-C2.c);        //两圆交点 
    if(dcmp(C1.r+C2.r-d)<0)return 0;
    if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0;
    double a=angle(C2.c-C1.c);
    double da=acos((d*d+C1.r*C1.r-C2.r*C2.r)/(2*d*C1.r));
    Point p1=C1.getpoint(a+da),p2=C1.getpoint(a-da);
    if(p1==p2){
        sol.push_back(p1);return 1;
    };
    sol.push_back(p1),sol.push_back(p2);
    return 2;
}
int get_tangents(Point p,Circle C,vector<Point>& sol){
    Vector u=C.c-p;        //切线 
    double dis=length(u);
    if(dcmp(dis-C.r)<0)return 0;
    if(!dcmp(dis-C.r)){
        sol.push_back(rotate(u,pi/2));return 1;
    }
    double ang=asin(C.r/dis);
    sol.push_back(rotate(u,ang));sol.push_back(rotate(u,-ang));
    return 2;
}
View Code

3.0 凸包

4.0 半平面交

5.0 自适应Simpson积分

double simpson(double a,double b){
    double c=a+(b-a)/2;
    return (F(a)+4*F(c)+F(b))*(b-a)/6.0;
}
double asr(double a,double b,double eps,double A){
    double c=a+(b-a)/2;
    double L=simpson(a,c),R=simpson(c,b);
    if(fabs(L+R-A)<eps*15)return (L+R)+(L+R-A)/15;
    return asr(a,c,eps/2,L)+asr(c,b,eps/2,R);
}
View Code

6.0 旋转卡壳

数学

1.0 欧几里得算法

LL gcd(LL a,LL b){
    return (b==0)?a:gcd(b,a%b);
}
View Code

1.1 扩展欧几里得算法

void exgcd(LL a,LL b,LL& d,LL& x,LL& y){
    if(!b){d=a,x=1,y=0;}
    else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
View Code

2.0 乘法逆元

LL inv(LL a,LL p){
    LL d,x,y;
    exgcd(a,p,d,x,y);
    return (d==1)?(x+p)%p:-1;
}
View Code

3.0 FFT(UOJ#34. 多项式乘法)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define MAXN 400005
#define pi acos(-1)
using namespace std;
int n,m;
struct cp
{
    double r,i;
    cp(double r=0,double i=0):r(r),i(i){}
    cp operator + (const cp& A)
    {return cp(r+A.r,i+A.i);}
    cp operator - (const cp& A)
    {return cp(r-A.r,i-A.i);}
    cp operator * (const cp& A)
    {return cp(r*A.r-i*A.i,r*A.i+i*A.r);}
}a[MAXN],b[MAXN];
void brc(cp* x,int l)
{
    int k=l/2;
    for(int i=1;i<l-1;i++)
    {
        if(i<k)swap(x[i],x[k]);
        int j=l/2;
        while(j<=k)
        {
            k-=j;
            j>>=1;
        }
        if(k<j)k+=j;
    }
}
void fft(cp* x,int l,int on)
{
    brc(x,l);
    for(int h=2;h<=l;h<<=1)
    {
        cp wn(cos(2*on*pi/h),sin(2*on*pi/h));
        for(int i=0;i<l;i+=h)
        {
            cp w(1,0);
            for(int j=i;j<i+h/2;j++)
            {
                cp u=x[j];
                cp t=w*x[j+h/2];
                x[j]=u+t;
                x[j+h/2]=u-t;
                w=w*wn;
            }
        }
    }
    if(on==-1)for(int i=0;i<l;i++)x[i].r/=l;
}
int main()
{
    scanf("%d%d",&n,&m);
    n++,m++;
    int l=1;
    while(l<n*2||l<m*2)l<<=1;
    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        a[i]=cp(x,0);
    }
    for(int i=n;i<l;i++)a[i]=cp(0,0);
    for(int i=0;i<m;i++)
    {
        int x;
        scanf("%d",&x);
        b[i]=cp(x,0);
    }
    for(int i=m;i<l;i++)b[i]=cp(0,0);
    fft(a,l,1);fft(b,l,1);
    for(int i=0;i<l;i++)a[i]=a[i]*b[i];
    fft(a,l,-1);
    for(int i=0;i<=n+m-2;i++)
    {
        int x=(int)(a[i].r+0.5); 
        printf("%d ",x);
    }
    return 0;
}
View Code
4.0 NTT
5.0 欧拉函数
void phi_table()
{
    phi[1]=1;
    for(int i=1;i<=n;i++)
    {
        if(!phi[i])
        for(int j=i;j<=n;j+=i)
        {
            if(!phi[j])phi[j]=j;
            phi[j]=phi[j]*(i-1)/i;
        }
    }
}
View Code

6.0 中国剩余定理(CodeVS 3990 中国余数定理 2)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long LL;
LL n,a,b,c[15],m[15],M=1,res=0;
LL read()
{
    LL x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)x=1,y=0;
    else exgcd(b,a%b,y,x),y-=x*(a/b);
}
int main()
{
    n=read(),a=read(),b=read();
    for(int i=1;i<=n;i++)
    m[i]=read(),c[i]=read(),M*=m[i];
    for(int i=1;i<=n;i++)
    {
        LL t=M/m[i],x,y;
        exgcd(t,m[i],x,y);
        x=(x+m[i])%m[i];
        res=(res+((x*t)%M*c[i])%M)%M;
    }
    if(a>res)
    {
        if((a-res)%M==0)res+=(a-res)/M*M;
        else res+=((a-res)/M+1)*M;
    }
    if(res>b||res<a){printf("0\n0\n");return 0;}
    printf("%lld\n%lld\n",(b-res)/M+1,res);
    return 0;
}
View Code

6.1 扩展中国剩余定理(POJ 2891 Strange Way to Express Integers

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define MAXN 50005
using namespace std;
typedef long long LL;
LL k,c[MAXN],m[MAXN];
LL read()
{
    LL x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
void exgcd(LL a,LL b,LL &d,LL &x,LL& y)
{
    if(!b)d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
LL inv(LL a,LL p)
{
    LL d,x,y;exgcd(a,p,d,x,y);
    return (x+p)%p==0?p:(x+p)%p;
}
int main()
{
    LL m1,m2,c1,c2;
    while(~scanf("%lld",&k))
    {
        for(int i=1;i<=k;i++)
            m[i]=read(),c[i]=read();
        for(int i=2;i<=k;i++)
        {
            m1=m[i-1],m2=m[i],c1=c[i-1],c2=c[i];
            LL t=gcd(m1,m2);
            if((c2-c1)%t!=0){c[k]=-1;break;}
            m[i]=m1*m2/t;
            c[i]=inv(m1/t,m2/t)*((c2-c1)/t)%(m2/t)*m1+c1;
            c[i]=(c[i]%m[i]+m[i])%m[i];
        }
        printf("%lld\n",c[k]);
    }
    return 0;
}
View Code

7.0 Lucas

7.1 扩展Lucas

其他

1.0 高精度

posted @ 2017-04-16 00:30  Zars19  阅读(605)  评论(4编辑  收藏  举报