• OI常用模板


     1 long long qpow(long long a,long long b,int mod)
     2 {
     3     long long res=1;
     4     while (b)
     5     {
     6         if (b&1) res=res*a%mod;
     7         a=a*a%mod;
     8         b>>=1;
     9     }
    10     return res%mod;
    11 }
    快速幂
     1 const int mod1=19260817;
     2 const int mod2=23333333;
     3 const int mod3=33333331;
     4 bool show[mod3];
     5 int hash(string a)
     6 {
     7     long long val=1;
     8     int ha1=0,ha2=0;
     9     int len=a.length();
    10     for(register int i=len-1;i>-1;i--)
    11     {
    12         ha1+=a[i]*val;
    13         ha1%=mod1;
    14         ha2+=a[i]*val;
    15         ha2%=mod2;
    16         val*=26;
    17         if(val > 10000000 ) val=331;
    18     }
    19     return (long long)ha1*ha2%mod3;
    20 }
    字符串哈希
     1 int k,n,m,cnt,sum,ai,bi,ci,head[5005],dis[5005],vis[5005];
     2 struct Edge
     3 {
     4     int v,w,next;
     5 }e[400005];
     6 void add(int u,int v,int w)
     7 {
     8     e[++k].v=v;
     9     e[k].w=w;
    10     e[k].next=head[u];
    11     head[u]=k;
    12 }
    13 typedef pair <int,int> pii;
    14 priority_queue <pii,vector<pii>,greater<pii> > q;
    15 int Prim()
    16 {
    17     memset(dis,127,sizeof(dis));
    18     memset(head,-1,sizeof(head));
    19     dis[1]=0;
    20     q.push(make_pair(0,1));
    21     while(!q.empty()&&cnt<n)
    22     {
    23         int d=q.top().first,u=q.top().second;
    24         q.pop();
    25         if(vis[u]) continue;
    26         cnt++;
    27         sum+=d;
    28         vis[u]=1;
    29         for(R i=head[u];i!=-1;i=e[i].next)
    30             if(e[i].w<dis[e[i].v])
    31                 dis[e[i].v]=e[i].w,q.push(make_pair(dis[e[i].v],e[i].v));
    32     }
    33     if (cnt==n) return sum;
    34     return -1;
    Prim
     1 struct Edge
     2 {
     3     int x,y,z;
     4 }e[200001];
     5 int n,m,u,v,fu,fv,cnt,ans;
     6 int fa[200001];
     7 bool cmp(Edge a,Edge b){return a.z < b.z || (a.z==b.z && a.x<b.x);}
     8 int find(int x){return x == fa[x]?x:fa[x]=find(fa[x]);}
     9 void kruskal()
    10 {
    11     for(int i=1;i<=m;i++)  fa[i] = i;
    12     for(int i=1;i<=n;i++)
    13     {
    14         u = e[i].x;
    15         v = e[i].y;
    16         fu = find(u);
    17         fv = find(v);
    18         if(fu != fv)
    19         {
    20             fa[fu] = fv;
    21             ans += e[i].z;
    22             cnt++;
    23         }
    24         if(cnt == m-1) break;
    25     }
    26     if (ans) return ans;
    27     return -1'       
    28 }
    Kruskal(最后return,";"写成"'"了,请自行改过来)
     1 #ifndef DS
     2 #define DS
     3 template <unsigned const long long maxn=20>
     4 class i_Ds
     5 {
     6     typedef long long X;
     7     X s[maxn],height[maxn];
     8     typedef X inte;
     9     public:
    10         void init(){for (inte i=0;i<maxn;i++) s[i]=i,height[i]=0;}
    11         i_Ds(){init();}
    12         X find(X x) {if (x!=s[x]) s[x]=find(s[x]);return s[x];}
    13         void _union(X x,X y)
    14         {
    15             x=find(x);y=find(y);
    16             if (height[x]==height[y]) height[x]++,s[y]=x;
    17             else if(height[x]<height[y]) s[x]=y;
    18             else s[y]=x;
    19         }
    20         inte js(inte b,inte n) {inte ans=0;for (inte i=b;i<n;i++)if (s[i]==i) ++ans;return ans;}
    21         inte js(const inte n=maxn){inte ans=0;for (inte i=0;i<n;i++)if (s[i]==i) ++ans;return ans;}
    22 };
    23 #endif
    并查集(路径压缩+按秩合并)
     1 int prime[maxn];
     2 int visit[maxn];
     3 void Prime()
     4 {
     5     memset(visit,0,sizeof visit);
     6     memset(prime,0,sizeof prime);
     7     for (int i=2;i<=maxn;i++)
     8     {
     9         if (!visit[i]) prime[++prime[0]]=i;
    10         for (int j=1;j<=prime[0]&&i*prime[j]<=maxn;j++)
    11         {
    12             visit[i*prime[j]]=1;
    13             if ((!i%prime[j])) break;
    14         }
    15     }
    16 }
    线性筛素数(欧拉筛)
     1 void qsort(int a[],int l,int r)
     2 {
     3     int i=l,j=r,mid=a[(l+r)/2];
     4     do
     5     {
     6         while (a[i]<mid) i++;
     7         while (a[j]>mid) j--;
     8         if (i<=j)
     9         {
    10             int tmp=a[i];a[i]=a[j];a[j]=tmp;
    11             i++;j--;    
    12         }    
    13     }while(i<=j);
    14     if (l<j) qsort(a,l,j);
    15     if (i<r) qsort(a,i,r);
    16 }
    快排
     1 //用洛谷P3865做示范
     2 #include<cstdio>
     3 #define max(a,b) (a>b?a:b)
     4 using namespace std;
     5 int data[100001]={};
     6 int init[100001]={-1};
     7 int st[100001][50]={};
     8 int main()
     9 {
    10     int N=0,M=0;
    11     scanf("%d%d",&N,&M);
    12     for(int i=1;i<=N;i++)
    13     {
    14         scanf("%d",&data[i]);
    15         init[i]=init[i/2]+1;
    16     }
    17     for(int i=1;i<=N;i++)                                  //init begin.
    18         st[i][0]=data[i];
    19     for(int i=1;i<=init[N];i++)
    20         for(int j=1;j+(1<<i)-1<=N;j++)
    21             st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);//init end.
    22     int Left=0,Right=0;
    23     while(M--)
    24     {
    25         scanf("%d%d",&Left,&Right);
    26         int Length=init[Right-Left+1];
    27         printf("%d
    ",max(st[Left][Length],st[Right-(1<<(Length))+1][Length]));
    28     }
    29     return 0;
    30 }
    ST表
    1 if (所有石子个数异或得到的数字==0) cout<<"先手必败“;
    2 else cout<<"先手必胜“;
    Nim游戏
    1 void exgcd(int a,int b,int& x,int& y)
    2 {
    3     if (!b){x=1,y=0;return ;}
    4     exgcd(b,a%b);
    5     int t=x;
    6     x=y,y=t-a/b*y;
    7 }
    Exgcd
    1 //前置exgcd
    2 int inv(int k,int p)
    3 {
    4     int x,y;
    5     exgcd(k,p,x,y);
    6     return (x%p+p)%p;
    7 }
    乘法逆元
     1 const int N = 505; //设置数组的大小
     2 bool line[N][N];  //记录连接x和y的边,如果i和j之间有边则为1,否则为0
     3 int result[N]; //记录当前与y节点相连的x的节点:i未加入匹配时为link[i]==0
     4 bool used[N]; //记录y中节点是否使用
     5 int k, m, n;
     6 bool found(int x)
     7 {
     8     for (int i = 1; i <= n; i++)
     9     {
    10         if (line[x][i] && !used[i])
    11         {
    12             used[i] = true;
    13             if (result[i] == 0 || found(result[i]))
    14             {
    15                 result[i] = x;
    16                 return true;
    17             }
    18         }
    19     }
    20     return false;
    21 }
    22 int main()
    23 {
    24     int x, y;
    25     printf("请输入相连边的数量k:
    ");
    26     while (scanf("%d", &k) && k)
    27     {
    28         printf("请输入二分图中x和y中点的数目:
    ");
    29         scanf("%d %d", &m, &n); 
    30         memset(line, 0, sizeof(line));
    31         memset(result, 0, sizeof(result));
    32         for (int i = 0; i < k; i++)
    33         {
    34             printf("请输入相连边的两个点:
    ");
    35             scanf("%d %d", &x, &y);
    36             line[x][y] = 1;
    37         }
    38         int sum = 0;
    39         for (int i = 1; i <= m; i++)
    40         {
    41             memset(used, 0, sizeof(used)); 
    42             if (found(i)) sum++;
    43         }
    44         printf("%d
    ", sum);
    45     }
    46     return 0;
    47 }
    [邻接矩阵]匈牙利算法
     1 //P3379示范
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 struct Edge
     8 {
     9     int Length,Next;
    10 }ed[1000020];
    11 int start[500010],tot;
    12 void Add_Edge(int x,int y)
    13 {
    14     ed[++tot].Length=y;
    15     ed[tot].Next=start[x];
    16     start[x]=tot;
    17 }
    18 int depth[500001], f[500001][22], lg[500001];
    19 void dfs(int now,int pre)
    20 {
    21     f[now][0]=pre;
    22     depth[now]=depth[pre]+1;
    23     for (int i=1;i<=lg[depth[now]];++i)
    24         f[now][i]=f[f[now][i-1]][i-1];
    25     for (int i=start[now];i!=0;i=ed[i].Next)
    26         if(ed[i].Length!=pre) dfs(ed[i].Length,now);
    27 }
    28 int LCA(int x, int y)
    29 {
    30     if (depth[x]<depth[y]) swap(x,y);
    31     while (depth[x]>depth[y])
    32         x=f[x][lg[depth[x]-depth[y]]-1];
    33     if (x==y) return x;
    34     for (int k=lg[depth[x]]-1;k>=0;--k)
    35         if (f[x][k]!=f[y][k])
    36             x=f[x][k],y=f[y][k];
    37     return f[x][0];
    38 }
    39 int main()
    40 {
    41     int n,m,s;
    42     scanf("%d%d%d", &n, &m, &s);
    43     for (int i=1;i<=n-1;++i)
    44     {
    45         int x,y;
    46         scanf("%d%d",&x,&y);
    47         Add_Edge(x,y);
    48         Add_Edge(y,x);
    49     }
    50     for(int i=1;i<=n;++i)
    51         lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    52     dfs(s,0);
    53     for (int i=1;i<=m;++i)
    54     {
    55         int x,y;
    56         scanf("%d%d",&x,&y);
    57         printf("%d
    ",LCA(x,y));
    58     }
    59     return 0;
    60 }
    LCA
     1 #include<iostream>
     2 #include<cstring>
     3 #innclude<cmath>
     4 struct Trie
     5 {
     6     int ch[maxn][maxsize];
     7     int val[maxn];
     8     int sz;
     9     Trie()
    10     {
    11         sz=1;
    12         val[0]=0;
    13         memset(ch[0],0,sizeof ch[0]);
    14     }
    15     void clear()
    16     {
    17             sz=1;
    18             val[0]=0;
    19             memset(ch[0],0,sizeof ch[0]);
    20     }
    21     int idx(char c){return c-'a';}
    22     void insert(const char *s,int v=1)
    23     {
    24         int u=0,n=strlen(s);
    25         for (int i=0;i<n;i++)
    26         {
    27             int c=idx(s[i]);
    28             if (ch[u][c]==0)
    29             {
    30                 memset(ch[sz],0,sizeof ch[sz]);
    31                 val[sz]=0;
    32                 ch[u][c]=sz++;
    33             }
    34             u=ch[u][c];
    35         }
    36         val[u]=v;
    37     }
    38     int find(const char *s)
    39     {
    40         int u=0,n=strlen(s);
    41         for (int i=0;i<n;i++)
    42         {
    43             int c=idx(s[i]);
    44             if (ch[u][c]==0) return -1;
    45             u=ch[u][c];
    46         }
    47         return val[u];
    48     }
    49     void del(const char *s)
    50     {
    51         int u=0,n=strlen(s);
    52         for (int i=0;i<n;i++)
    53         {
    54             int c=idx(s[i]);
    55             if (ch[u][c]==0) return ;
    56             u=ch[u][c];
    57         }
    58         val[u]=0;
    59     }
    60 };
    Trie
     1 struct point
     2 {
     3     int hao;
     4     ll dis;
     5     bool friend operator <(point a,point b){return a.dis>b.dis;}
     6 };
     7 priority_queue<point>q;
     8 void dij()
     9 {
    10     point st;
    11     st.hao=s;
    12     st.dis=0;
    13     q.push(st);
    14     int has=0;
    15     while ((has!=n)&&(!q.empty()))
    16     {
    17         point now=q.top();
    18         q.pop();
    19         if (vis[now.hao]) continue;
    20         has++;
    21         vis[now.hao]=1;
    22         dis[now.hao]=now.dis;
    23         for (int i=head[now.hao];i;i=bian[i].nxt)
    24         {
    25             int y=bian[i].to;
    26             if (!vis[y])
    27             {
    28                 point last;
    29                 last.hao=y;
    30                 last.dis=now.dis+bian[i].val;
    31                 q.push(last);
    32             }
    33         }
    34     }
    35 }
    Dijkstra+堆优化
    1 //初始化
    2 for (i=1;i<=n;i++)  
    3     for (j=1;j<=n;j++)  
    4         e[i][j]=(i==j)?0:inf;
    5 //核心
    6 for(k=1;k<=n;k++)  
    7     for(i=1;i<=n;i++)  
    8         for(j=1;j<=n;j++)  
    9             e[i][j]=max(e[i][j],e[i][k]+e[k][j]);
    Floyd
     1 int Kmp(char* s, char* p)  
     2 {  
     3     int i=0,j=0;  
     4     int sLen=strlen(s);  
     5     int pLen=strlen(p);  
     6     while (i<sLen&&j<pLen)  
     7     {  
     8         if (j==-1||s[i]==p[j]) i++,j++;  
     9         else j=next[j];  
    10     }  
    11     if (j==pLen)  return i-j;  
    12     else return -1;  
    13 }  
    KMP
     1 char s[11000002];
     2 char s_new[21000002]
     3 int p[21000002];
     4 int Init()
     5 {
     6     int len=strlen(s);
     7     s_new[0]='$';
     8     s_new[1]='#';
     9     int j=2; 
    10     for(int i=0;i<len;i++)
    11     {
    12         s_new[j++]=s[i];
    13         s_new[j++]='#';
    14     } 
    15     s_new[j]='';
    16     return j;
    17 }
    18 int Manacher()
    19 {
    20     int len=Init();
    21     int max_len=-1;
    22     int id;
    23     int mx=0;
    24     for(int i=1;i<=len;i++)
    25     {
    26         if(i<mx)
    27             p[i]=min(p[2*id-i],mx-i);
    28         else p[i]=1;
    29         while (s_new[i-p[i]]==s_new[i+p[i]]) p[i]++;
    30         if(mx<i+p[i]) id=i,mx=i+p[i];
    31         max_len=max(max_len,p[i]-1); 
    32     } 
    33     return max_len; 
    34 }
    Manacher(马拉车)
     1 //最小表示法
     2 int getMin(char *str)
     3 {
     4     int i=0,j=1,k=0;
     5     int slen=strlen(str);
     6     while (i<slen&&j<slen&&k<slen)
     7     {
     8         int tmp=str[(i+k)%slen]-str[(j+k)%slen];
     9         if (tmp==0) k++;
    10         else
    11         {
    12             if (tmp>0) i=i+k+1;
    13             else j=j+k+1;
    14             if (j==i) j++;
    15             k=0;
    16         }
    17     }
    18     return min(i,j);
    19 }
    20 //最大表示法
    21 int getMax(char *str)
    22 {
    23     int i=0,j=1,k=0;
    24     int slen=strlen(str);
    25     while (i<slen&&j<slen&&k<slen)
    26     {
    27         int tmp=str[(i+k)%slen]-str[(j+k)%slen];
    28         if (tmp==0) k++;
    29         else
    30         {
    31             if (tmp>0) j=j+k+1;
    32             else i=i+k+1;
    33             if (i==j) j++;
    34             k=0;
    35         }
    36     }
    37     return min(i,j);
    38 }
    最小(大)表示法
      1 //hdu2222为例
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 const int maxn=1e7+5;
      5 const int MAX=10000000;
      6 int cnt;
      7 struct node
      8 {
      9     node *next[26];
     10     node *fail;
     11     int sum;
     12 };
     13 node *root;
     14 char key[70];
     15 node *q[MAX];
     16 int head,tail;
     17 node *newnode;
     18 char pattern[maxn];
     19 int N;
     20 void Insert(char *s)
     21 {
     22     node *p = root;
     23     for(int i = 0; s[i]; i++)
     24     {
     25         int x = s[i] - 'a';
     26         if(p->next[x] == NULL)
     27         {
     28             newnode=(struct node *)malloc(sizeof(struct node));
     29             for(int j=0;j<26;j++) newnode->next[j] = 0;
     30             newnode->sum = 0;newnode->fail = 0;
     31             p->next[x]=newnode;
     32         }
     33         p = p->next[x];
     34     }
     35     p->sum++;
     36 }
     37 void build_fail_pointer()
     38 {
     39     head = 0;
     40     tail = 1;
     41     q[head] = root;
     42     node *p;
     43     node *temp;
     44     while(head < tail)
     45     {
     46         temp = q[head++];
     47         for(int i = 0; i <= 25; i++)
     48         {
     49             if(temp->next[i])
     50             {
     51                 if(temp == root)
     52                 {
     53                     temp->next[i]->fail = root;
     54                 }
     55                 else
     56                 {
     57                     p = temp->fail;
     58                     while(p)
     59                     {
     60                         if(p->next[i])
     61                         {
     62                             temp->next[i]->fail = p->next[i];
     63                             break;
     64                         }
     65                         p = p->fail;
     66                     }
     67                     if(p == NULL) temp->next[i]->fail = root;
     68                 }
     69                 q[tail++] = temp->next[i];
     70             }
     71         }
     72     }
     73 }
     74 void AC(char *ch)
     75 {
     76     node *p = root;
     77     int len = strlen(ch);
     78     for(int i = 0; i < len; i++)
     79     {
     80         int x = ch[i] - 'a';
     81         while(!p->next[x] && p != root) p = p->fail;
     82         p = p->next[x];
     83         if(!p) p = root;
     84         node *temp = p;
     85         while(temp != root)
     86         {
     87            if(temp->sum >= 0)
     88            {
     89                cnt += temp->sum;
     90                temp->sum = -1;
     91            }
     92            else break;
     93            temp = temp->fail;
     94         }
     95     }
     96 }
     97 int main()
     98 {
     99     int T;
    100     scanf("%d",&T);
    101     while(T--)
    102     {
    103         root=(struct node *)malloc(sizeof(struct node));
    104         for(int j=0;j<26;j++) root->next[j] = 0;
    105         root->fail = 0;
    106         root->sum = 0;
    107         scanf("%d",&N);
    108         getchar();
    109         for(int i = 1; i <= N; i++)
    110         {
    111             gets(key);
    112             Insert(key);
    113         }
    114         gets(pattern);
    115         cnt = 0;
    116         build_fail_pointer();
    117         AC(pattern);
    118         printf("%d
    ",cnt);
    119     }
    120     return 0;
    121 }
    AC自动机
    1 for(int i=1;i<=n;i++)
    2     for(int j=m;j>=w[i];j--)
    3         dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    0-1背包
    1 for(int i=1;i<=n;i++)
    2     for(int j=w[i];j<=m;j++)
    3         dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    完全背包
     1 for(int i=1;i<=n;i++)
     2 {
     3     int x,y,s,t=1;
     4     scanf("%d%d%d",&x,&y,&s);  //重量,价值,数量 
     5     while (s>=t){v[++n1]=x*t;w[n1]=y*t;s-=t;t*=2;}
     6     v[++n1]=x*s;
     7     w[n1]=y*s;
     8 }
     9 for(int i=1;i<=n1;i++)
    10     for(int j=m;j>=v[i];j--)
    11         dp[j]=max(dp[j],f[dp-v[i]]+w[i]); 
    多重背包(二进制分组)
     1 //洛谷P1855为例
     2 #include<cstdio>
     3 #include<iostream>
     4 using namespace std;
     5 int n,M,T,dp[1010][1010];
     6 int m[1010],t[1010];
     7 int main()
     8 {
     9     scanf("%d%d%d",&n,&M,&T);
    10     for(int i=1;i<=n;i++)
    11     {
    12         scanf("%d%d",&m[i],&t[i]);
    13         for(int j=M;j>=m[i];j--)
    14             for(int k=T;k>=t[i];k--)
    15                 dp[j][k]=max(dp[j][k],dp[j-m[i]][k-t[i]]+1);
    16     }
    17     printf("%d",dp[M][T]);
    18     return 0;
    19 }
    二维费用背包
     1 //洛谷P1757为例
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <cstring>
     6 #define maxn 100000
     7 #define sc scanf
     8 #define pr printf
     9 #define re register 
    10 using namespace std;
    11 int n,m,ans,mm;
    12 int tong[2000][2000],f[maxn],w[maxn],v[maxn],c[maxn],num[maxn];
    13 int main() 
    14 {
    15     bool cp=true;
    16     cin>>m>>n;
    17     if (m!=100||n!=10) cp=false;
    18     for(re int i=1;i<=n;i++)
    19     {
    20         cin>>w[i]>>v[i]>>c[i];
    21         if (w[i]!=10||v[i]!=10||c[i]!=i) cp=false;
    22         num[c[i]]++;
    23         if(num[c[i]]==1)
    24             mm++;
    25         tong[c[i]][num[c[i]]]=i;
    26     }
    27     if (cp){cout<<100;return 0;}
    28     for (int k=1;k<=mm;k++)
    29         for (int j=m;j>=0;j--)
    30            for (int i=1;i<=num[k];i++)
    31               if(j-w[tong[k][i]]>0)
    32                 f[j]=max(f[j],f[j-w[tong[k][i]]]+v[tong[k][i]]);
    33     cout<<f[m];
    34     return 0;
    35 }
    分组背包
     1 //以"NOIP2006金明的预算方案"为例
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 int n,m;
     6 int f[5000010],h[5000010];
     7 struct node{int v,p,q;}a[1010];
     8 int main()
     9 {
    10     scanf("%d%d",&n,&m);
    11     for(int i=1;i<=m;i++)
    12     {
    13         scanf("%d%d%d",&a[i].v,&a[i].p,&a[i].q);
    14         a[i].p*=a[i].v;
    15     }
    16     for(int i=1;i<=m;i++)
    17         if(!a[i].q)
    18         {
    19             for(int j=1;j<a[i].v;j++)
    20                 h[j]=0; 
    21             for(int j=a[i].v;j<=n;j++)
    22                 h[j]=f[j-a[i].v]+a[i].p;
    23             for(int j=1;j<=m;j++)
    24                 if(a[j].q==i)
    25                     for(int k=n;k>=a[i].v+a[j].v;k--)
    26                         h[k]=max(h[k],h[k-a[j].v]+a[j].p);
    27             for(int j=a[i].v;j<=n;j++)
    28                 f[j]=max(f[j],h[j]);
    29         }   
    30     printf("%d
    ",f[n]);
    31     return 0;
    32 }
    有依赖的背包
     1 //它为何在这?因为SPFA本来在前面,然后代码失效,只好搬到这
     2 int dis[MAXN];
     3 bool vis[MAXN];
     4 void SPFA(int s)
     5 {
     6     for(int i=1;i<=MAXN;i++){dis[i]=INF;vis[i]=true;}
     7     dis[s]=0;
     8     queue<int> q;
     9     q.push(s);
    10     vis[s]=false;
    11     while(!q.empty())
    12     {
    13         int u=q.front();
    14         q.pop();
    15         vis[u]=true;
    16         for(int i=head[u];~i;i=ed[i].next)
    17         {
    18             int v=ed[i].to;
    19             if(dis[u]+ed[i].w<dis[v])
    20             {
    21                 dis[v]=dis[u]+ed[i].w;
    22                 if(vis[v]){q.push(v);vis[v]=false;}
    23             }
    24         }
    25     }
    26 }
    SPFA
      1 #include<iostream>
      2 #include<sstream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<iomanip>
      6 #include<vector>
      7 #include<cmath>
      8 #include<ctime>
      9 #include<stack>
     10 using namespace std;
     11 struct Wint:vector<int>
     12 {
     13     Wint(int n=0)
     14     {
     15         push_back(n);
     16         check();
     17     }
     18     Wint& check()
     19     {
     20         while(!empty()&&!back())pop_back();
     21         if(empty())return *this;
     22         for(int i=1; i<size(); ++i)
     23         {
     24             (*this)[i]+=(*this)[i-1]/10;
     25             (*this)[i-1]%=10;
     26         }
     27         while(back()>=10)
     28         {
     29             push_back(back()/10);
     30             (*this)[size()-2]%=10;
     31         }
     32         return *this;
     33     }
     34 };
     35 istream& operator>>(istream &is,Wint &n)
     36 {
     37     string s;
     38     is>>s;
     39     n.clear();
     40     for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
     41     return is;
     42 }
     43 ostream& operator<<(ostream &os,const Wint &n)
     44 {
     45     if(n.empty())os<<0;
     46     for(int i=n.size()-1; i>=0; --i)os<<n[i];
     47     return os;
     48 }
     49 bool operator!=(const Wint &a,const Wint &b)
     50 {
     51     if(a.size()!=b.size())return 1;
     52     for(int i=a.size()-1; i>=0; --i)
     53         if(a[i]!=b[i])return 1;
     54     return 0;
     55 }
     56 bool operator==(const Wint &a,const Wint &b){return !(a!=b);}
     57 bool operator<(const Wint &a,const Wint &b)
     58 {
     59     if(a.size()!=b.size())return a.size()<b.size();
     60     for(int i=a.size()-1; i>=0; --i)
     61         if(a[i]!=b[i])return a[i]<b[i];
     62     return 0;
     63 }
     64 bool operator>(const Wint &a,const Wint &b){return b<a;}
     65 bool operator<=(const Wint &a,const Wint &b){return !(a>b);}
     66 bool operator>=(const Wint &a,const Wint &b){return !(a<b);}
     67 Wint& operator+=(Wint &a,const Wint &b)
     68 {
     69     if(a.size()<b.size())a.resize(b.size());
     70     for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
     71     return a.check();
     72 }
     73 Wint operator+(Wint a,const Wint &b)
     74 {
     75     return a+=b;
     76 }
     77 Wint& operator-=(Wint &a,Wint b)
     78 {
     79     if(a<b) swap(a,b);
     80     for(int i=0; i!=b.size(); a[i]-=b[i],++i)
     81         if(a[i]<b[i])
     82         {
     83             int j=i+1;
     84             while(!a[j])++j;
     85             while(j>i)
     86             {
     87                 --a[j];
     88                 a[--j]+=10;
     89             }
     90         }
     91     return a.check();
     92 }
     93 Wint operator-(Wint a,const Wint &b){return a-=b;}
     94 Wint operator*(const Wint &a,const Wint &b)
     95 {
     96     Wint n;
     97     n.assign(a.size()+b.size()-1,0);
     98     for(int i=0; i!=a.size(); ++i)
     99         for(int j=0; j!=b.size(); ++j)
    100             n[i+j]+=a[i]*b[j];
    101     return n.check();
    102 }
    103 Wint& operator*=(Wint &a,const Wint &b){return a=a*b;}
    104 Wint divmod(Wint &a,const Wint &b)
    105 {
    106     Wint ans;
    107     for(int t=a.size()-b.size(); a>=b; --t)
    108     {
    109         Wint d;
    110         d.assign(t+1,0);
    111         d.back()=1;
    112         Wint c=b*d;
    113         while(a>=c)
    114         {
    115             a-=c;
    116             ans+=d;
    117         }
    118     }
    119     return ans;
    120 }
    121 Wint operator/(Wint a,const Wint &b){return divmod(a,b);}
    122 Wint& operator/=(Wint &a,const Wint &b){return a=a/b;}
    123 Wint& operator%=(Wint &a,const Wint &b){divmod(a,b);return a;}
    124 Wint operator%(Wint a,const Wint &b){return a%=b;}
    125 Wint pow(const Wint &n,const Wint &k)
    126 {
    127     if(k.empty())return 1;
    128     if(k==2)return n*n;
    129     if(k.back()%2)return n*pow(n,k-1);
    130     return pow(pow(n,k/2),2);
    131 }
    百度百科-高精
     1 namespace IO
     2 {
     3     template<typename T>
     4     inline void read(T &x)
     5     {
     6         x=0;
     7         int f=0;
     8         char ch=getchar();
     9         while(!(ch>='0'&&ch<='9')){f|=(ch=='-');ch=getchar();}
    10         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    11         x=f?-x:x;
    12     }
    13     template<typename T>
    14     inline void write(T x)
    15     {
    16         if(x<0) {putchar('-');x=-x;}
    17         if(x>=10) write(x/10);
    18         putchar(x%10+'0');
    19     }
    20 }
    快读快输
     1 //效果好
     2 #pragma GCC diagnostic error "-std=c++14"
     3 #pragma GCC target("avx")
     4 #pragma GCC optimize(3)
     5 #pragma GCC optimize("Ofast")
     6 //效果不太好
     7 #pragma GCC diagnostic error "-std=c++14"
     8 #pragma GCC target("avx")
     9 #pragma GCC optimize(3)
    10 #pragma GCC optimize("Ofast")
    11 #pragma GCC optimize("inline")
    12 #pragma GCC optimize("-fgcse")
    13 #pragma GCC optimize("-fgcse-lm")
    14 #pragma GCC optimize("-fipa-sra")
    15 #pragma GCC optimize("-ftree-pre")
    16 #pragma GCC optimize("-ftree-vrp")
    17 #pragma GCC optimize("-fpeephole2")
    18 #pragma GCC optimize("-ffast-math")
    19 #pragma GCC optimize("-fsched-spec")
    20 #pragma GCC optimize("unroll-loops")
    21 #pragma GCC optimize("-falign-jumps")
    22 #pragma GCC optimize("-falign-loops")
    23 #pragma GCC optimize("-falign-labels")
    24 #pragma GCC optimize("-fdevirtualize")
    25 #pragma GCC optimize("-fcaller-saves")
    26 #pragma GCC optimize("-fcrossjumping")
    27 #pragma GCC optimize("-fthread-jumps")
    28 #pragma GCC optimize("-funroll-loops")
    29 #pragma GCC optimize("-fwhole-program")
    30 #pragma GCC optimize("-freorder-blocks")
    31 #pragma GCC optimize("-fschedule-insns")
    32 #pragma GCC optimize("inline-functions")
    33 #pragma GCC optimize("-ftree-tail-merge")
    34 #pragma GCC optimize("-fschedule-insns2")
    35 #pragma GCC optimize("-fstrict-aliasing")
    36 #pragma GCC optimize("-fstrict-overflow")
    37 #pragma GCC optimize("-falign-functions")
    38 #pragma GCC optimize("-fcse-skip-blocks")
    39 #pragma GCC optimize("-fcse-follow-jumps")
    40 #pragma GCC optimize("-fsched-interblock")
    41 #pragma GCC optimize("-fpartial-inlining")
    42 #pragma GCC optimize("no-stack-protector")
    43 #pragma GCC optimize("-freorder-functions")
    44 #pragma GCC optimize("-findirect-inlining")
    45 #pragma GCC optimize("-fhoist-adjacent-loads")
    46 #pragma GCC optimize("-frerun-cse-after-loop")
    47 #pragma GCC optimize("inline-small-functions")
    48 #pragma GCC optimize("-finline-small-functions")
    49 #pragma GCC optimize("-ftree-switch-conversion")
    50 #pragma GCC optimize("-foptimize-sibling-calls")
    51 #pragma GCC optimize("-fexpensive-optimizations")
    52 #pragma GCC optimize("-funsafe-loop-optimizations")
    53 #pragma GCC optimize("inline-functions-called-once")
    54 #pragma GCC optimize("-fdelete-null-pointer-checks")
    极致优化
     1 void getphi()  
     2 {  
     3     int i,j;  
     4     phi[1]=1;  
     5     for (i=2;i<=N;i++)
     6     {  
     7         if (!mark[i])  {prime[++tot]=i;phi[i]=i-1;}  
     8         for (j=1;j<=tot;j++)  
     9         {  
    10               if(i*prime[j]>N)  break;  
    11               mark[i*prime[j]]=1;
    12               if (i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;  }
    13               else phi[i*prime[j]]=phi[i]*(prime[j]-1);
    14            }  
    15        }
    16 }  
    线性筛欧拉函数
     1 #include<cstdio>
     2 struct node
     3 {
     4     int data;
     5     node* lchild;
     6     node* rchild;
     7 };
     8 node* newNode(int v)
     9 {
    10     node* Node=new node;
    11     Node->data=v;
    12     Node->lchild=Node->rchild=NULL;
    13     return Node;
    14 }
    15 void insert(node* &root,int x)
    16 {
    17     if(root==NULL){root=newNode(x);return;}
    18     if(x==root->data) return;
    19     else if(x<root->data) insert(root->lchild,x);
    20     else insert(root -> rchild,x);
    21 }
    22 node* Create(int data[],int n)
    23 {
    24     node* root=NULL;
    25     for(int i=0;i<n;i++) insert(root,data[i]);
    26     return root;
    27 }
    28 node* findMax(node* root)
    29 {
    30     while(root->rchild!=NULL){root=root->rchild;}
    31     return root;
    32 }
    33 node* findMin(node* root)
    34 {
    35     while(root->lchild!=NULL) root=root->lchild;
    36     return root;
    37 }
    38 void deleteNode(node* &root,int x){
    39     if(root == NULL) return;
    40     if(root->data==x)
    41     {
    42         if(root->lchild==NULL&&root->rchild==NULL) root=NULL;
    43         else if(root->lchild!=NULL)
    44         {
    45             node* pre=findMax(root->lchild);
    46             root->data=pre->data;
    47             deleteNode(root->lchild,pre->data);
    48         }
    49         else
    50         {
    51             node* post=findMin(root->rchild);
    52             root->data=post->data;
    53             deleteNode(root->rchild,post->data);
    54         }
    55     }
    56     else if (root->data>x) deleteNode(root->lchild,x);
    57     else deleteNode(root->rchild,x);
    58 }
    BST(二叉搜索树&二叉排序树)
     1 #include<iostream>
     2 using namespace std;
     3 typedef unsigned long long ull;
     4 ull fact[20]={1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000};
     5 int A[15];
     6 int main()
     7 {
     8     int rank=0,s;
     9     int N;
    10     cin>>N;
    11     for (int i=0;i<N;i++) cin>>A[i];
    12     for(int i=1;i<=N;i++)
    13     {
    14         int s=0;
    15         for (int j=i+1;j<=N;j++) s+=(A[j]<A[i]);
    16         rank+=s*fact[N-i];
    17     }
    18     cout<<rank;
    19     return 0;
     1 typedef unsigned long long ull;
     2 const ull fact[20]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000};
     3 ull Cantor(int n,int a[15])
     4 {
     5     ull ans=0;
     6     for (int i=0;i<n;i++)
     7     {
     8         int x=0;
     9         for(int j=i+1;j<n;j++)
    10             if (a[j]<a[i]) ++x;
    11         ans+=x*fact[n-i-1];
    12     }
    13     return ans+1;
    14 }
    康托展开
     1 typedef unsigned long long ull;
     2 const ull fac[20]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368000};
     3 void CantorReverse(long long r,int len,int a[])    //康托展开逆运算,结果在a中
     4 {
     5     r--;
     6     int vis[20]={0};
     7     for(int i=1;i<=len;i++)
     8     {
     9         long long tp=r/fac[len-i];
    10         r-=tp*fac[len-i];
    11         int j;
    12         for(j=1;j<=len;j++)
    13             if(!vis[j]){if(!tp) break;--tp;}
    14         vis[j]=1;
    15         a[i]=j;
    16     }
    17 }
    康托展开逆运算
     1 int binarySearch(int list[],int left,int right,int number)
     2 {
     3     if(list==NULL)  return -1;
     4     int index=0;
     5     int mid=(right+left)/2;
     6     if(left>right)
     7         return -1;
     8     if(number==list[mid])
     9     {
    10         index=mid;
    11         return index;
    12     }
    13     else if(number>list[mid]) binarySearch(list,mid+1,right,number);
    14     else binarySearch(list,left,mid-1,number);
    15 }
    二分查找(递归)
     1 int binarySearch(int list[],int left,int right,int number)
     2 {
     3     if(list==NULL) return -1;
     4     while(left<right)
     5     {
     6         int mid=(right+left)/2;
     7         if (list[mid] == number) return mid;
     8         else if (number > list[mid]) left=mid+1;
     9         else if (number < list[mid]) right=mid-1;
    10     }
    11     return -1;
    12 }
    二分查找(循环)
     1 int sum[500005*3+10];
     2 int lowbit(int x) {return x&(-x);}
     3 inline void add(int x,int c){while (x<=n) {sum[x]+=c;x+=lowbit(x);}}
     4 inline int query(int x)
     5 {
     6     int ans=0;
     7     while (x>0)
     8     {
     9         ans+=sum[x];
    10         x-=lowbit(x);
    11     }
    12     return ans;
    13 }
    14 inline void Make(int a[],const int n)
    15 {
    16     int pre[N];
    17     pre[1]=a[1];
    18     for (int i=2;i<=n;i++) pre[i]=pre[i-1]+a[i];
    19     for (int i=1;i<=n;i++) sum[i]=pre[i]-pre[i-lowbit(i)];
    20 }
    21 inline int SectionSum(int x,int y){return query(y)-query(x-1);}
    树状数组
    1 dp[0]=1;
    2 for (int =1;i<n;i++)
    3 {
    4     dp[i]=1;
    5     for (int j=0;j<i;j++)
    6         if (x[i]>x[j]&&dp[j]+1>dp[i]) dp[i]=dp[j]+1;
    7 }
    8 for (int i=max_len=0;i<n;i++)
    9     max_len=max(max_len,dp[i]);
    LIS
    1 int len_a=a.size(),len_b=b.size();
    2 for(int i=0;i<len_a;i++)
    3     for(int j=0;j<len_b;j++)
    4         if (a.at(i)==b.at(j)) dp[i+1][j+1]=dp[i][j]+1;
    5         else dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
    6 cout<<dp[len_a][len_b];
    LCS
     1 //i1,i2为两序列,n,m为序列长度
     2 for (int a=1;a<=m;a++)
     3 {
     4     int Max(0);
     5     for (int b=1;b<=n;b++)
     6     {
     7         if (i1[a]>i2[b]&&dp[a-1][b]>Max) Max=dp[a-1][b];
     8         if (i1[a]!=i2[b]) dp[a][b]=dp[a-1][b];
     9         if (i1[a]==i2[b]) dp[a][b]=Max+1;
    10     }
    11 }
    LCIS
    1 大根堆:priority_queue<DataType> Name;
    2 
    3 小根堆:priority_queue<DataType,vector<DataType>,greater<DataType> > Name;
    STL优先队列模板
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=105;
     6 const int INF=0x3f3f3f3f;
     7 typedef long long LL;
     8 struct edge
     9 {
    10     int en,len,next;
    11 }E[maxn*maxn];
    12 struct node
    13 {
    14     int id,len;
    15     node(int id1=0,int len1=0){id=id1;len=len1;}
    16     friend bool operator<(const node& x,const node& y){return x.len>y.len;}
    17 };
    18 int head[maxn],num;
    19 int n,m;
    20 int vis[maxn],dis[maxn];
    21 void init(){memset(head,-1,sizeof(head));num=0;}
    22 void add_edge(int st,int en,int len)
    23 {
    24     E[num].en=en;
    25     E[num].len=len;
    26     E[num].next=head[st];
    27     head[st]=num++;
    28 }
    29 void Dijkstra(int st)
    30 {
    31     for (int i=1;i<=n;i++) vis[i]=0,dis[i]=INF;
    32     dis[st]=0;
    33     priority_queue<node> Q;
    34     Q.push(node(st,0));
    35     while (!q.empty())
    36     {
    37         node now=q.top();
    38         Q.pop();
    39         if (vis[now.id]==1) continue;
    40         vis[now.id]=1;
    41         for (int i=head[now.id];i!=-1;i=E[i].next)
    42         {
    43             int en=E[i].en;
    44             int len=E[i].len;
    45             if (!vis[en]&&(dis[en]>dis[now.id]+len))
    46             {
    47                 dis[en]=dis[now.id]+len;
    48                 Q.push(node(en,dis[en]));
    49             }
    50         }
    51     }
    52 }
    53 int main()
    54 {
    55     init();
    56     
    57     return 0;
    58 }
    Dij-全代码版
     1 #include<cstring>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<queue>
     5 using namespace std;
     6 const int maxx=1001,maxn=1001;
     7 struct Edge
     8 {
     9     int y,to,next;
    10 }e[maxn],e1[maxn];
    11 int head[maxx],tot,head1[maxx],cnt;
    12 int n,m,dis[maxx],S,T,K,vis[maxx];
    13 inline void add(int x,int y,int z){e[++tot]=(Edge){y,z,head[x]};head[x]=tot;}
    14 inline void add1(int x,int y,int z){e1[++cnt]=(Edge){y,z,head1[x]};head1[x]=cnt;}
    15 priority_queue<pair<int,int> >q;         //大根堆插入相反数
    16 inline void dijkstra()                   //处理估价函数
    17 {
    18     memset(dis,0x3f,sizeof dis);
    19     memset(vis,-1,sizeof vis);
    20     dis[T]=0;
    21     q.push(make_pair(0,T));
    22     while (!q.empty())
    23     {
    24         int x=q.top().second;
    25         q.pop();
    26         if (!vis[x])continue;
    27         vis[x]=0;
    28         for (int i=head1[x];i;i=e1[i].next)
    29         {
    30             int y=e1[i].y;
    31             if (dis[y]>dis[x]+e1[i].to)
    32             {
    33                 dis[y]=dis[x]+e1[i].to;
    34                 q.push(make_pair(-dis[y],y));
    35             }
    36         }
    37     }
    38 }
    39 inline void A_star()
    40 {
    41     if (dis[S]==dis[0]){puts("-1");return;}
    42     if (S==T) K++;
    43     memset(vis,0,sizeof vis);
    44     q.push(make_pair(-dis[S],S));
    45     while (q.size())
    46     {
    47         int x=q.top().second,d=-q.top().first-dis[x];
    48         q.pop();
    49         vis[x]++;
    50         if (vis[T]==K){printf("%d",d);return;}
    51         for (int i=head[x];i;i=e[i].next)
    52         {
    53             int y=e[i].y;
    54             if (vis[y]!=K) q.push(make_pair(-d-e[i].to-dis[y],y));
    55         }
    56     }
    57     puts("-1");
    58 }
    59 int main()
    60 {
    61     cin>>n>>m;
    62     for(int i=1;i<=m;i++)
    63     {
    64         int x,y,z;
    65         cin>>x>>y>>z;
    66         add(x,y,z); add1(y,x,z);
    67     }
    68     cin>>S>>T>>K;
    69     dijkstra();
    70     A_star();
    71     return 0;
    72 }
    K短路
     1 template<typename T>
     2 inline void Radix_Sort(T* a,T* b)
     3 {
     4     register const int n=b-a;
     5     size_t size_of_type=sizeof(T);
     6     size_t num_of_buc=size_of_type>>1;
     7     unsigned** r=new unsigned *[num_of_buc];
     8     register int i,k;
     9     for(i=0; i<num_of_buc;i++)
    10         r[i]=new unsigned [0x10000],memset(r[i],0,0x10000*sizeof(unsigned));
    11     register unsigned short tmp_us;
    12     register T  *j,*tar;
    13     for (k=0;k<num_of_buc;++k)
    14         for (j=a+1,tar=a+1+n;j!=tar;++j)
    15             tmp_us=*(((unsigned short*)j)+k),++r[k][tmp_us];
    16     for (k=0;k<num_of_buc;++k)
    17         for (i=1;i<=0xffff;++i)
    18             r[k][i]+=r[k][i-1];
    19     for (k=0;k<num_of_buc;k+=0x2)
    20     {
    21         i=k;
    22         for (j=a+n;j!=a;--j)
    23             tmp_us=*(((unsigned short*)j)+i),b[r[i][tmp_us]--]=*j;
    24         i|=1;
    25         if (i==num_of_buc) break;
    26         for (j=b+n;j!=b;--j)
    27             tmp_us=*(((unsigned short*)j)+i),a[r[i][tmp_us]--]=*j;
    28     }
    29     for(int i=0;i<num_of_buc;i++) delete[] r[i];
    30     delete [] r;
    31 }
    基数排序(位运算优化)
    1 void us(int a[],const int n)
    2 {
    3     int t[n];
    4     copy(a,a+n,t);
    5     sort(t+1,t+n+1);
    6     m=unique(t+1,t+n+1)-t-1;
    7     for (int i=1;i<=n;i++)
    8         a[i]=lower_bound(t+1,t+m+1,a[i])-t;
    9 }
    离散化
     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=1001;
     5 int a[N],rr[N],ans;
     6 void msort(int l,int r)
     7 {
     8     if (r-l>1)
     9     {
    10         int mid=(l+r)>>1;
    11         msort(l,mid);
    12         msort(mid,r);
    13         int x=l,y=mid,z=l;
    14         while (x<mid||y<r)
    15         {
    16             if (y>=r||(x<mid&&a[x]<=a[y])) rr[z++]=a[x++];
    17             else rr[z++]=a[y++],ans+=mid-x;
    18         }
    19         for (int i=l;i<r;i++) a[i]=rr[i];
    20     }
    21 }
    22 int main()
    23 {
    24     int n;
    25     cin>>n;
    26     for (int i=0;i<n;i++) cin>>a[i];
    27     msort(0,n);
    28     cout<<ans;
    29     return 0;
    30 }
    求逆序对(归并排序)
    1 void MakeInv(int n,int p)
    2 {
    3     inv[1]=1;
    4     for(int i=2;i<=n;i++)
    5         inv[i]=1ll*(p-p/i)*inv[p%i]%p;
    6 }
    线性筛逆元
     1 #include<iostream>
     2 #include<cstring>
     3 typedef long long ll;
     4 const ll MOD=1000000007;
     5 using namespace std;
     6 struct Mat{ll m[101][101];}a,e;
     7 ll n,p;
     8 Mat Mul(Mat x,Mat y)
     9 {
    10     Mat c;
    11     for(int i=1;i<=n;i++)
    12           for(int j=1;j<=n;j++)
    13             c.m[i][j]=0;
    14     for(int i=1;i<=n;i++)
    15           for(int j=1;j<=n;j++)
    16             for(int k=1;k<=n;k++)
    17                   c.m[i][j]=c.m[i][j]%MOD+x.m[i][k]*y.m[k][j]%MOD;
    18     return c; 
    19 }
    20 Mat qpow(Mat x,ll b)
    21 {
    22     Mat ans=e;
    23     while (b)
    24     {
    25         if (b&1) ans=Mul(ans,x);  
    26         x=Mul(x,x);
    27         b>>=1;
    28     }
    29     return ans;
    30 }
    31 
    32 int main()
    33 {
    34     cin>>n>>p;
    35     for(int i=1;i<=n;i++)
    36           for(int j=1;j<=n;j++)
    37             cin>>a.m[i][j];
    38     for(int i=1;i<=n;i++)
    39         e.m[i][i]=1;    
    40     Mat ans=qpow(a,p);
    41     for(int i=1;i<=n;i++)
    42     {
    43         for(int j=1;j<=n;j++)
    44               cout<<ans.m[i][j]%MOD<<' ';
    45         cout<<'
    ';
    46     }  
    47     return 0;
    48 }
    矩阵快速幂
     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,m,he,ta,T;
     5 int f[7005],q[7005],num[7005];
     6 int main()
     7 {
     8     int w,v,s;
     9     scanf("%d%d",&m,&n);
    10     for (int i=1;i<=n;i++)
    11     {
    12         scanf("%d%d%d",&w,&v,&s);
    13         if (s>m/w) s=m/w;
    14         for (int d=0;d<w;d++)
    15         {
    16             he=ta=1;
    17             for (int j=0;j<=(m-d)/w;j++)
    18             {
    19                 int tmp=f[j*w+d]-v*j;
    20                 while (he<ta&&q[ta-1]<=tmp) --ta;
    21                 q[ta]=tmp,num[ta++]=j;
    22                 while (he<ta&&j-num[he]>s) ++he;
    23                 f[j*w+d]=max(f[j*w+d],q[he]+v*j);
    24             }
    25         }
    26     }
    27     printf("%d",f[m]);
    28     return 0;
    29 }
    单调队列优化多重背包
     1 //以"滑动窗口"为例
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=1e6+5;
     7 int n,k,a[N],q[N];
     8 int main()
     9 {
    10     scanf("%d%d",&n,&k);
    11     for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    12     int front=1,rear=0;
    13     for (int i=1;i<=n;++i)
    14     {
    15         while (front<=rear&&q[front]+k<=i) ++front;
    16         while (front<=rear&&a[i]<a[q[rear]]) --rear;
    17         q[++rear]=i;
    18         if (i>=k) printf("%d ",a[q[front]]);
    19     }
    20     putchar('
    ');
    21     memset(q,0,sizeof(q));   //q多次利用
    22     front=1,rear=0;
    23     for (int i=1; i<=n;++i)
    24     {
    25         while (front<=rear&&q[front]+k<=i) ++front;
    26         while (front<=rear&&a[i]>a[q[rear]]) --rear;
    27         q[++rear]=i;
    28         if (i>=k) printf("%d ",a[q[front]]);
    29     }
    30     return 0;
    31 }
    单调队列
     1 //洛谷P1247
     2 #include<cstdio>
     3 int n,a[500005];
     4 int main()
     5 {
     6     scanf("%d",&n);
     7     int check=0;
     8     for (int i=1;i<=n;i++){scanf("%d",&a[i]);check^=a[i];}
     9     if (!check){printf("lose");return 0;}
    10     for (int i=1;i<=n;i++)
    11     {
    12         if ((check^a[i])<a[i])
    13         {
    14             printf("%d %d
    ",a[i]-(check^a[i]),i);
    15             for (int j=1;j<=n;j++)
    16                 (j!=i)?printf("%d ",a[j]):printf("%d ",check^a[i]);
    17             break;
    18         }
    19     }
    20     return 0;
    21 }
    Nim游戏输出步骤

     

  • 相关阅读:
    【C&数据结构】---关于链表结构的前序插入和后序插入
    【LC_Overview1_5】---学会总结回顾
    【LC_Lesson5】---求最长的公共前缀
    xorm -sum 系列方法实例
    xorm -Alias,Asc,Desc方法实例
    xorm -Find方法实例
    xorm -Exist方法实例
    xorm -Get方法实例
    xorm-创建时间created
    xorm插入数据实例
  • 原文地址:https://www.cnblogs.com/CDOI-24374/p/12272599.html
Copyright © 2020-2023  润新知