ACM模板

自己用的图论模板

图论模板【点击进去】

最短路
Dijkstra
//复杂度:V*V
//注意:初始化c,vis,pre,dis
//     输入c[][]的时候判断是否大于之前的值
//     建图的时候注意是什么图
const int inf = (0x7fffffff)>>1;
const int edgeNum = 205;

int c[edgeNum][edgeNum];
int dis[edgeNum];
bool vis[edgeNum];
int pre[edgeNum];

void Dijkstra(int n,int v, int *dis,int c[edgeNum][edgeNum])
{
      memset(pre,0, sizeof(pre));
       for(int i=0;i<n;i++){
            vis[i]=0;
            dis[i]=c[i][v];
             if(dis[i]==inf)pre[i]=0;
             else pre[i]=v;
      }

      vis[v]=1; int u=v;
       for(int ii=1;ii<n;ii++){
             int minL=inf;
             for(int i=0;i<n;i++)
                   if(vis[i]==0&&dis[i]<minL){
                        u=i;
                        minL=dis[i];
                  }
            vis[u]=1;

             for(int i=0;i<n;i++)
                   if(vis[i]==0&&dis[i]>(dis[u]+c[u][i])){
                        dis[i]=(dis[u]+c[u][i]);
                        pre[i]=u;
                  }
      }
}
//验证的打印路径
void Dijkstra()
{
       for(int i=1;i<=N;i++)
      {
            vis[i]=0;
            dis[i]=c[1][i];
             if(dis[i]!=inf)pre[i]=1;
      }
      vis[1]=1;
       for(int i=2;i<=N;i++)
      {
             int u=1;int minL=inf;
             for(int j=1;j<=N;j++)
            {
                   if(vis[j]==0&&dis[j]<minL)
                  {
                        minL=dis[j];
                        u=j;
                  }
            }
            vis[u]=1;
             for(int j=1;j<=N;j++)
            {
                   if(vis[j]==0&&(dis[j]>dis[u]+c[u][j])){
                        dis[j]=dis[u]+c[u][j];
                        pre[j]=u;
                  }
            }
      }
}

/*==================================================*\
| Dijkstra数组实现O(N^2)
| Dijkstra --- 数组实现(在此基础上可直接改为STL的Queue实现)
| lowcost[] --- beg到其他点的最近距离
| path[] -- beg为根展开的树,记录父亲结点
\*==================================================*/
#define INF 0x03F3F3F3F
const int N=99999999;
int path[N], vis[N];
void Dijkstra(int cost[][N], int lowcost[N], int n, int beg){
       int i, j, min;
      memset(vis, 0, sizeof(vis));
      vis[beg] = 1;
       for (i=0; i<n; i++){
            lowcost[i] = cost[beg][i]; path[i] = beg;
      }
      lowcost[beg] = 0;
      path[beg] = -1;  // 树根的标
       int pre = beg;
       for (i=1; i<n; i++){
            min = INF;
             for (j=0; j<n; j++)
                   // 下面的加法可能导致溢出,INF不能取太大
                   if (vis[j]==0&&
                        lowcost[pre]+cost[pre][j]<lowcost[j])
                  {
                        lowcost[j] = lowcost[pre] + cost[pre][j];
                        path[j] = pre;
                  }
                   for (j=0; j<n; j++)
                         if (vis[j] == 0 && lowcost[j] < min){
                              min = lowcost[j]; pre = j;
                        }
                        vis[pre] = 1;
      }
}
  


/*==================================================*\

| 二分图匹配(匈牙利算法 BFS 实现) 
| INIT: g[][]
 邻接矩阵 ; 
| CALL: res =
 MaxMatch();Nx, Ny
 初始化!!! 
|
 优点:适用于稀疏二分图,边较少,增广路较短。 
|
 匈牙利算法的理论复杂度是 O(VE) 
\*==================================================*/

int MAXN = 1000;
int   uN, vN;                // u, v数y目,要a初始 化!!!
bool   g[MAXN][MAXN];      // g[i][j] 表示xi与yj相连
int   xM[MAXN], yM[MAXN];   // 输出量
bool   chk[MAXN];            // 辅助量检查某3轮y[v]是否被check 
bool   SearchPath( int   u){
         int   v;
         for (v = 0; v < vN; v++)
               if (g[u][v] && !chk[v])
            {
                  chk[v] =   true ;
                     if (yM[v] == -1 || SearchPath(yM[v]))
                  {
                        yM[v] = u; xM[u] = v;
                           return   true   ;
                  }
            }
               return   false   ;
}
int   MaxMatch(){
         int   u, ret = 0 ;
      memset(xM, -1,   sizeof   (xM));
      memset(yM, -1,   sizeof   (yM));
         for (u = 0; u < uN; u++)
               if (xM[u] == -1){
                  memset(chk,   false ,   sizeof   (chk));
                     if (SearchPath(u)) ret++;
            }
         return   ret;

常见的错误:
注意的东西:

数据结构模板【点击进去】

其实跟线段树的思想差不多,都是二分的思想,分治

//初始化,效率:初始化是O(n * log n + m)n是总区间,m是询问数量,每次询问的效率是O(1)
for (i=1;i<=N;i++) 
    { 
        scanf(   "%d" ,&a[i]); 
        rmq1[i][0]=a[i];  
        rmq2[i][0]=a[i];                        
    }    //rmq[i][j]  起e点是i长度是2^j,这a段区间的最值
    DP(N);

void DP(int N)
{
    int i,j,k;
    for(i=1;i<= int(log(double (N))/log(2.0));i++) 
        for(j=1;j<=N;j++)
        {
            dp1[j][i]=mmax(dp1[j][i-1],dp1[j+ int(pow(2.0,i-1))][i-1]);
            dp2[j][i]=mmin(dp2[j][i-1],dp2[j+ int(pow(2.0,i-1))][i-1]);
        }
}
int search(int i,int j)
{
     int k=(int )(log((double)(j-i+1))/log(2.0));
     return mmax(dp1[i][k],dp1[j-(1<<k)+1][k])-mmin(dp2[i][k],dp2[j-(1<<k)+1][k]);
}
  
作用:一边寻找一边压缩路径,减少下次找的时间。
查找一颗树中某个节点的祖先,例如查找k的祖先,在不断通过父亲节点寻找祖先结束是,顺便把从k到最终祖先节点S中经过的所有节点的祖先都指向S,那么以后搜索就能把时间降低到O(1),但是如果全部都查找了,那效率就是O(n)n是节点个数
int   ancestor[large+1]; //第i个节点祖先
int   find( int   x)
{
         if (ancestor[x]!=x)
            ancestor[x]=find(ancestor[x]);   //路径压缩
         return   ancestor[x];
}


//传统数组(共n个元素)的元素修改和连续元素求和的复杂度分别为O(1)和O(n)。树状数     
//组通过将线性结构转换成伪树状结构(线性结构只能逐个扫描元素,而树状结构可以实现跳跃式扫描),使得//修改和求和复杂度均为O(lgn),
//二维树状数组
#include<iostream>
using namespace std;
#define maxn 1003
int row, col, ar[Max][Max];//那个图
int lowbit(int x){
    return x & (-x);
}
void add(int i, int j, int w){

    int tmpj;
    while(i <= row){
        tmpj = j;
        while(tmpj <= col){
            ar[i][tmpj] += w;
            tmpj += lowbit(tmpj);
        }
        i += lowbit(i);
    }
}
int sum(int i, int j){

    int tmpj, ans = 0;
    while(i > 0){
        tmpj = j;
        while(tmpj > 0){
            ans += ar[i][tmpj];
            tmpj -= lowbit(tmpj);
        }
        i -= lowbit(i);
    }
    return ans;
}

int main(){
    int n, ord, x, y, xx, yy, w;
    while(scanf("%d%d", &ord, &n) != EOF){
        memset(ar, 0, sizeof(ar));
        row = col = n;
        while(scanf("%d", &ord) && ord != 3){
            if(ord == 1){
                scanf("%d%d%d", &x, &y, &w);
                x ++, y ++;    //  二维的其实下标为[1][1],这个要记得。
                add(x, y, w);
            }else{
                scanf("%d%d%d%d", &x, &y, &xx, &yy);
                x ++, y ++, xx ++, yy ++;
                int ans = sum(xx, yy)-sum(x-1, yy)-sum(xx, y-1)+sum(x-1,y-1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

//建树是log n * n
struct
{
         int   l;
         int   r;
         int   col;
         bool   same;
}nnode[5*maxn];
int   L,T,O;
void   buildtree( int   left, int   right,   int   u)
{
      nnode[u].l=left;
      nnode[u].r=right;
      nnode[u].col=color[1];
      nnode[u].same=1;
         if (left==right) return   ;
         int   mid=(left+right)/2;
      buildtree(left,mid,u<<1);
      buildtree(mid+1,right,(u<<1)+1);
}
int   colnum;

void   getdown( int   u)
{
         int   temp=nnode[u].col;
      nnode[u].same=0;
      nnode[u<<1].same=1;
      nnode[u<<1].col=temp;
      nnode[(u<<1)+1].same=1;
      nnode[(u<<1)+1].col=temp;
}
void   update( int   left, int   right,   int   col, int   u)
{
         if (nnode[u].l==left&&right==nnode[u].r)
      {
            nnode[u].same=1;
            nnode[u].col=color[col];
               return   ;
      }
         //if(color[col]==nnode[u].col)return;
         if (nnode[u].same)getdown(u);

         if (right<=nnode[u<<1].r)
      {
            update(left,right,col,u<<1);
      }

         else   if   (left>=nnode[(u<<1)+1].l)
      {
            update(left,right,col,(u<<1)+1);
      }
         else
      {
            update(left,nnode[u<<1].r,col,u<<1);
            update(nnode[(u<<1)+1].l,right,col,(u<<1)+1);
      }
      nnode[u].col=nnode[u<<1].col|nnode[(u<<1)+1].col;
}
void   query( int   l, int   r,   int   u)
{
         if (nnode[u].same){colnum|=nnode[u].col; return   ;}
         if (nnode[u].l==l&&nnode[u].r==r)
      {
            colnum|=nnode[u].col;
               return ;
      }
         if (r<=nnode[u<<1].r)
      {
            query(l,r,u<<1);
      }
         else   if   (l>=nnode[(u<<1)+1].l)
      {
            query(l,r,(u<<1)+1);
      }
         else
      {
            query(l,nnode[u<<1].r,u<<1);
            query(nnode[(u<<1)+1].l,r,(u<<1)+1);
      }
}

数论模板【点击进去】

//矩阵快速幂
#define  maxn 33
int  n,k,m;
struct  Matrix
{
        int  data[maxn][maxn];
        void  operator  =(Matrix a)
      {
              for ( int  i=0;i<n;i++)
                    for ( int  j=0;j<n;j++)
                  {
                        data[i][j] = a.data[i][j];
                  }
      }
      Matrix  operator +(Matrix a)
      {
            Matrix c;
              for ( int  i=0;i<n;i++)
                    for ( int  j=0;j<n;j++){
                        c.data[i][j]=data[i][j]+a.data[i][j];
                        c.data[i][j]%=m;
                  }
                    return  c;
      }
      Matrix  operator *(Matrix a)
      {
            Matrix c;
              for ( int  i=0;i<n;i++)
                    for ( int  j=0;j<n;j++){
                          int  sum=0;
                          for ( int  k=0;k<n;k++){
                              sum+=data[i][k]*a.data[k][j];
                              sum%=m;
                        }
                        c.data[i][j]=sum%m;
                  }
                    return  c;
      }
        void  danwei()
      {
              for ( int  i=0;i<n;i++)
            {
                    for ( int  j=0;j<n;j++)
                  {
                          if (i==j)
                              data[i][j]=1;
                          else  data[i][j]=0;
                  }
            }
      }
}A;

Matrix Dan;
Matrix quickpow( int  k)
{
      Matrix B = A;
      Matrix c = Dan;
        while (k>0)
      {
              if (k&1)c = (c*B);
            k=k>>1;
            B=B*B;
      }
        return  c;
}

Matrix erfen( int  k)
{
        if (k==1) return  A;
        if (k%2==0)
      {
              return  erfen(k/2)*(Dan+quickpow(k/2));
      }
        return  erfen(k/2)*(Dan+quickpow(k/2))+quickpow(k);
}


//快速幂 log n 算法
long  long  quickpow( long  long  m, long  long  n,  long  long  k)
{  
        long  long  b = 1;
        while  (n > 0)
      {
              if  (n & 1)
                  b = (b*m)%k;
            n = n >> 1 ;
            m = (m*m)%k;
      }     return  b;
}


//欧拉函数 求1,2,3....n中D和n互质的个数
1:用时长
int  eula_phi( int  n)
{
        int  ans=1;
        int  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;
}
//
2:用时短
int euler_phi(int   n)
{
       int m=(int )sqrt(n+0.5);
       long long ans=n;
       for(int i=2;i<=m;i++)
      {
             if(n%i==0)
            {
                  n/=i;
                  ans=ans*(i-1)/i;
                   while(n%i==0)
                  {
                        n/=i;
                  }
            }
      }
       if(n>1)
            ans=ans*(n-1)/n;
       return ans;
}


//已验证 O(nloglogn) 打表,1~n中D的所有欧拉函数值,存储在phi[]中
void  phi_table( int  n,  int *phi)
{
        for  ( int  i=2;i<=n;i++)phi[i]=0;
      phi[1]=1;
        for  ( int  i=2;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*(i-1);
                  }
            }
      }
}






//打印素数表
#define  maxn 1000
int   pri[maxn];
int p[maxn];
int k;
void  init()
{
      memset(p,1,  sizeof (p));
        for ( int  i=2;i*i<maxn;i++)
              if (p[i])
            {
                    for ( int  j=i<<1;j<maxn;j+=i)
                        p[j]=0;
            }
            k=0;
              for ( int  i=2;i<maxn;i++)
                    if (p[i])pri[k++]=i;
}



//   排列组合模板,要用__int64。注意参数顺序!
__int64  C( int  m,  int  n)
{    
        if (m > n - m) m = n - m;  
        __int64  ans = 1, cou = m; 
        while (cou --)
      {
            ans *= n --;
              while (ans % m == 0 && m > 1)
                  ans /= m --;  
      }
        return  ans;
}



//打印组合数
#define  maxn 1000
int  c[maxn][maxn];
void  init()
{
        for ( int  i=0;i<maxn;i++) c[i][0]=c[i][i]=1;
        for ( int  i=2;i<maxn;i++)
              for ( int  j=1;j<i;j++)
                  c[i][j]=c[i-1][j-1]+c[i-1][j];
}



#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;

int gcd(int x,int y)
{return x%y==0?y:gcd(y,x%y);}
int main()
{
       int n,color;
       while(scanf("%d%d" ,&color,&n)!=EOF)
       {
             if(n==0&&color==0)break ;
             double c=color;
             if(n==0)
             {
                  cout<<0<<endl; continue;
             }
             double ans=pow(c,n);
             for(int i=1;i<n;i++)
             {
                  ans+=pow(c,gcd(i,n));
             }
             if(n%2==1)
                  ans+=n*pow(c,(n+1)/2);
             else
                  ans+=n/2*pow(c,n/2)+n/2*pow(c,n/2+1);
            ans=ans/(2*n);
            printf( "%0.f\n",ans);
       }
       return 0;
}



参数:a,b(输入)x,y(答案存储在这里)
返回:a和b的最小公约数
相当于求a关于-b的逆元
__int64 exGcd(__int64 a,__int64 b, __int64 &x,__int64 &y){
       if(b==0){
            x=1;
            y=0;
             return a;
      }
       __int64 g=exGcd(b,a%b,x,y);
       __int64 temp=x;
      x=y;
      y=temp-(a/b)*y;
       return g;
}
逆元:求a/b%c?
算法:如果bc互质,则答案等于a*d%c   d是b关于c的逆元
使用:a/b%c==a*k%c   =>  b*k-c*y=1
代入exGcd(b,c,k,y)
b是被除数   c是modle  k是要求的逆元   y是无关的东西





CF157E
//打印素数表和因式分解1到n(效率 是n*log(n))
#define maxn 100001//maxn是分解的最大的数
#define maxm 32  // maxm是log2(最大分解的数)

int  pri[maxn];//存储质数,但是没有maxn那么多,大概1/10
int k;//记录质数的个数


struct Node//x[i][0]是存储第i个因子,x[i][1]是存储第i个因子的数量,n是因子的个数
{
     int x[maxm][2];
     int n;
}nnode[maxn];//每个数字所包含的因子,如12:2,3

//Node nnodenum[maxn];//记录每个数的因子的数量,如12:2,1
void init()
{
     int p[maxn];
     memset(p,1, sizeof(p));
     for(int i=2;i*i<maxn;i++){
          if(p[i])
          {
               nnode[i].x[nnode[i].n++][0]=i;
               for(int j=i<<1;j<maxn;j+=i){
                    p[j]=0;
                    nnode[j].x[nnode[j].n++][0]=i;
               }
          }
     }
     k=0;
     for(int i=2;i<maxn;i++)
          if(p[i])pri[k++]=i;

     for(int i=2;i<maxn;i++)
     {
          int temp=i;
          for(int j=0;j<nnode[i].n;j++)
          {
               while(temp%nnode[i].x[j][0]==0)
               {
                    temp=temp/nnode[i].x[j][0];
                    nnode[i].x[j][1]++;
               }
          }
     }
}

//效率sqrt(n)*log n
struct Node//x[i][0]是存储第i个因子,x[i][1]是存储第i个因子的数量,n是因子的个数
{
     int x[maxm][2];
     int n;
}nnode[maxn];//每个数字所包含的因子,如12:2,3
void fenjie(int b,Node &a)//分解数字n,存储在a中a.n是因子的数量,a.x[i][0]是该因子、a.x[i][1]是因子的数量
{
     a.n=0;
     for(int i=0;i<maxm;i++)
          a.x[i][0]=a.x[i][1]=0;
     for(int i=0;i<k;i++)
     {
          if(b%pri[i]==0){
               b/=pri[i];
               a.x[a.n][0]=pri[i];
               a.x[a.n][1]++;
               while(b%pri[i]==0)
               {
                    a.x[a.n][1]++;
                    b/=pri[i];
               }
               a.n++;
          }
     }
     if(b>1){
          a.x[a.n][1]++;
          a.x[a.n++][0]=b;
     }
}

typedef __int64 LL
LL sum_dengbi(LL q,LL n) //等比是q,长度为n+1,1+q+q^2....+q^n
{
       if(n==0)return (LL)1;
       if(n%2==1)//奇数
             return ((1+quickpow(q,(n+1)/2,mo))*sum_dengbi(q,(n)/2))%mo;
       else return ((1+quickpow(q,(n)/2,mo))*sum_dengbi(q,(n-1)/2)+quickpow(q,n,mo))%mo;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值