Dear 时继

来源:互联网 发布:带网络连接的安全模式 编辑:程序博客网 时间:2024/04/29 00:21

NOIP模板整理

“愿我们的爱恨万古长存。”

基础部分

高精度

模拟版
//好丑QAQ

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 20005;int ca[MAXN],cb[MAXN],cc[MAXN];char a[MAXN],b[MAXN]; int lena,lenb; void jia(){    memset(ca,0,sizeof(ca));    memset(cb,0,sizeof(cb));    memset(cc,0,sizeof(cc));    for(int i = 0 ; i < lena; i ++)        ca[i] = a[lena - i - 1] - '0';    for(int i = 0 ; i < lenb; i ++)        cb[i] = b[lenb - i - 1] - '0';    int len = 0;    while(len <= lena + 2 || len <= lenb + 2)    {        cc[len] += ca[len] + cb[len];        cc[len + 1] += cc[len] / 10;        cc[len] %= 10;        len ++;    }    len += 3;    while(true)    {        if(cc[len] == 0) len --;        else    break;    }    if(len == 0)    {        puts("0");        return;    }    for(int i = len; i >= 0; i --)        printf("%d",cc[i]);    return;}void jian(){    memset(ca,0,sizeof(ca));    memset(cb,0,sizeof(cb));    memset(cc,0,sizeof(cc));    for(int i = 0 ; i < lena; i ++)        ca[i] = a[lena - i - 1] - '0';    for(int i = 0 ; i < lenb; i ++)        cb[i] = b[lenb - i - 1] - '0';    if(lena < lenb)    {        for(int i = 0; i < lenb; i ++)        {            cc[i] = ca[i];            ca[i] = cb[i];            cb[i] = cc[i];        }        cout << '-';        memset(cc,0,sizeof(cc));    }    else if(lena == lenb)    {        for(int i = lena - 1; i >= 0; i --)        {            if(ca[i] > cb[i]) break;            else if(ca[i] == cb[i]) continue;            else            {                for(int j = i; j >= 0; j --)                {                    cc[j] = ca[j];                    ca[j] = cb[j];                    cb[j] = cc[j];                }                cout << '-';                memset(cc,0,sizeof(cc));                break;            }        }    }    memset(cc,0,sizeof(cc));    int len = 0;    while(len <= lena + 2 || len <= lenb + 2)    {        if(ca[len] < cb[len])        {            ca[len] += 10;            ca[len + 1] --;        }        cc[len] += ca[len] - cb[len];        len ++;    }    len += 3;    while(true)    {        if(cc[len] == 0) len --;        else    break;    }    if(len == 0)    {        puts("0");        return;    }    for(int i = len; i >= 0; i --)        printf("%d",cc[i]);    return;}void cheng(){    memset(ca,0,sizeof(ca));    memset(cb,0,sizeof(cb));    memset(cc,0,sizeof(cc));    for(int i = 0 ; i < lena; i ++)        ca[i] = a[lena - i - 1] - '0';    for(int i = 0 ; i < lenb; i ++)        cb[i] = b[lenb - i - 1] - '0';    for(int i = 0; i <= lena + 3; i ++)        for(int j = 0; j <= lenb + 3; j ++)            cc[i + j] += ca[i] * cb[j];    for(int i = 0; i <= lena + lenb + 4; i ++)        if(cc[i] > 9)            cc[i + 1] += cc[i] / 10,cc[i] %= 10;    int len = lena + lenb + 3;    while(true)    {        if(cc[len] == 0) len --;        else    break;    }    if(len == 0)    {        puts("0");        return;    }    for(int i = len; i >= 0; i --)        printf("%d",cc[i]);    return;}/*void gc(int b)//高精除 {    bool shit=0;    for(int i=len;i>=2;i--)    {        ans[i-1]+=(ans[i]%b)*10;        ans[i]/=b;        if(!shit)        {            if(!ans[i])len--;            else shit=1;        }    }    ans[1]/=b;    ans[0]=len;}void ggc(int b)//高精除 {    bool shit=0;    for(int i=tt[0];i>=2;i--)    {        tt[i-1]+=(tt[i]%b)*10;        tt[i]/=b;        if(!shit)        {            if(!tt[i])tt[0]--;            else shit=1;        }    }    tt[1]/=b;}*/int main(){    cin >> a >> b;    lena = strlen(a);    lenb = strlen(b);    jia();    jian();    cheng();    return 0;}

子集枚举

//这个并没有用二进制处理

void ds(){    for(int i = 1; i <= n; i ++)        if(viv[i] == true)            printf("%d ",num[i]);    puts("");    return;}void dfs(int now){    if(now > n)     {        ds();        return;    }    for(int i = 0; i <= 1; i ++)    {        viv[now] = i;        dfs(now + 1);        viv[now] = false;    }    return;}

归并&&逆序对

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 200005;int n,num[MAXN],xc[MAXN];long long ans = 0;void work(int l,int r){    if(l == r) return;    int mid = (l + r) >> 1;    work(l,mid);work(mid + 1,r);    int ll = l,rl = mid + 1,now = 1;    while(ll <= mid && rl <= n)    {        if(num[ll] > num[rl])        {            xc[now] = num[rl];            now ++;rl ++;            ans += mid - ll + 1;        }        else        {            xc[now] = num[ll];            now ++,ll ++;        }    }    while(ll <= mid)    {        xc[now] = num[ll];        ll ++;now ++;    }    while(rl <= n)    {        xc[now] = num[rl];        rl ++;now ++;    }    int ssr = r - l + 1;    for(int i = 1; i <= ssr; i ++)        num[l - 1 + i] = xc[i];//!!!    return;}int main(){    memset(num,0,sizeof(num));    memset(xc,0,sizeof(xc));    scanf("%d",&n);    for(int i = 1; i <= n; i ++)        scanf("%d",&num[i]);    work(1,n);    printf("%lld\n",ans);    return 0;}

全排列

//x表示是否还有空位,当且仅当x>0时,继续放void qpl(int x){    if(x > 0)    {        for(int i = 1; i <= n; i++)        if(b[i]==0)//如果这一位上没有放数        {            ans[x]=i;//放上数            b[i]=1;//记录一下放上了数            qpl(x-1);//继续放数            b[i]=0;//放完数了,清空状态        }    }    else        for(int i = n; i >=1; i--)            printf("%d ",ans[i]);//放好了数,输出,即为一种排列        printf("\n");}

尺取法

int cqf(){    int l = 0,r = 0;    int ans = 0,len = MAXN;    while(true)    {        while(r <= n && ans < S)            r ++,ans += num[r];        if(ans < S)  break;        len = min(len,r - l + 1);        ans -= num[l ++];    }    return len < n ? len : 0;}

堆排

const int MAXN = 1000005;int n,s,heap[MAXN],cnt = 0;//小根堆 stl默认大根堆 void pop(){    heap[1] = heap[cnt];    int p = 1;    while(p * 2 + 1 <= cnt)    {        int l = p * 2,r = p * 2 + 1;        if(heap[l] < heap[p])        {            if(heap[r] < heap[l] && heap[r] < heap[p])                swap(l,r);//!!!!            swap(heap[l],heap[p]);            p = l;        }        else if(heap[r] < heap[p])        {            swap(heap[r],heap[p]);            p = r;        }        else             break;    }    cnt --;}void push(int x){    cnt ++;    int p = cnt;    heap[p] = x;    //顺序…… //  int l = p * 2,r = p * 2 + 1;    while(p != 1)    {        int f = p / 2;//!!!!!!        if(heap[f] > heap[p])        {            swap(heap[f],heap[p]);            p = f;        }        else            break;    }    return;}int main(){    scanf("%d",&n);    for(int i = 1; i <= n; i ++)    {        scanf("%d",&s);        push(s);    }    for(int i = 1; i <= n; i ++)    {        printf("%d ",heap[1]);        pop();    }    return 0;}

手动读入

inline int read(){    char ch = getchar();    int f = 1, x = 0;    while(!(ch >= '0' && ch <= '9')){if(ch == '-')f = -1;ch = getchar();}    while(ch >= '0' && ch <= '9') {x = x * 10 + (ch - '0');ch = getchar();}    return x * f;} 

⑧数码问题

爱情之路

数据结构

并查集

int find(int x){    return x == fa[x] ? x : fa[x] = find(fa[x]);}bool same(int x,int y){    return find(x) == find(y);}void merge(int x,int y){    x = find(x),y = find(y);    if(rank[x] < rank[y])   swap(x,y);    fa[x] = y;    if(rank[x] == rank[y])  rank[y] ++;    return;}

树状数组

int lowbit(int x){    return x&(-x);}void add(int x,int y){    while(x <= n)    {        tree[x] += y;        x += lowbit(x);    }    return;}int sum(int x){    int s = 0;    while(x)    {        s += tree[x];        x -= lowbit(x);    }    return s;}int answer(int x,int y){    return sum(y) - sum(x - 1);}int num[MAXN];int main(){    memset(tree,0,sizeof(tree));    scanf("%d",&n);    for(int i = 1; i <= n; i ++)    {        scanf("%d",&num[i]);        add(i,num[i] - num[i - 1]);    }    scanf("%d",&m);    for(int j = 1; j <= m; j ++)    {        scanf("%d",&t);        if(t == 1)        {            scanf("%d %d %d",&a,&b,&y);            add(a,y);            add(b + 1,-y);        }        else if(t == 2)        {            scanf("%d",&y);            printf("%d\n",sum(y));        }    }    return 0;}

线段树

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define L(x) (x << 1)//左儿子#define R(x) (x << 1 | 1)//右儿子#define sz(x) (tree[x].r - tree[x].l + 1)//区间大小using namespace std;const long long MAXN = 200000 + 5;long long num[MAXN];// l == 左;r == 右;p == now;struct dot{    long long l,r;    long long add,sum;//修改求和    long long min,max;//最值标记    bool xczhw;//没用打着玩……这是个梗QAQ}tree[MAXN << 2];//标记下放们 p == nowvoid update(long long p){    tree[p].sum = tree[L(p)].sum + tree[R(p)].sum;    tree[p].max = max(tree[L(p)].max,tree[R(p)].max);    tree[p].min = min(tree[L(p)].min,tree[R(p)].min);    return;}void spread(long long p){    if(!tree[p].add)    return;    tree[L(p)].max += tree[p].add;    tree[R(p)].max += tree[p].add;    tree[L(p)].min += tree[p].add;    tree[R(p)].min += tree[p].add;    tree[L(p)].add += tree[p].add;    tree[R(p)].add += tree[p].add;    tree[L(p)].sum += tree[p].add * sz(L(p));    tree[R(p)].sum += tree[p].add * sz(R(p));    tree[p].add = 0;//!!!!!!!    update(p);    return;}//简单的建立void build(long long l,long long r,long long p){    tree[p].l = l,tree[p].r = r;    if(l == r)    {        tree[p].min = tree[p].max = tree[p].sum = num[l];        return;    }    long long mid = (tree[p].l + tree[p].r) >> 1;    build(l,mid,L(p));    build(mid+1,r,R(p));    update(p);    return;}//区间修改void change(long long l,long long r,long long p,long long v){    if(l <= tree[p].l && tree[p].r <= r)    {        tree[p].add += v;        tree[p].min += v;        tree[p].max += v;        tree[p].sum += v*sz(p);        return;    }    spread(p);    long long mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid) change(l,r,L(p),v);    if(mid < r) change(l,r,R(p),v);    update(p);    return;}//区间求和long long ask_sum(long long l,long long r,long long p){    if(l <= tree[p].l && tree[p].r <= r)    {        return tree[p].sum;    }    spread(p);    long long ans = 0,mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid) ans += ask_sum(l,r,L(p));    if(mid < r) ans += ask_sum(l,r,R(p));    update(p);    return ans;}//区间最大值long long ask_max(long long l,long long r,long long p){    if(l <= tree[p].l && tree[p].r <= r)    {        return tree[p].max;    }    spread(p);    long long ans = 0,mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid) ans = max(ans,ask_max(l,r,L(p)));    if(mid < r) ans = max(ans,ask_max(l,r,R(p)));    update(p);    return ans;}//区间最小值long long ask_min(long long l,long long r,long long p){    if(l <= tree[p].l && tree[p].r <= r)    {        return tree[p].min;    }    spread(p);    long long ans = 2333333,mid = (tree[p].l + tree[p].r) >> 1;    if(l <= mid) ans = min(ans,ask_min(l,r,L(p)));    if(mid < r) ans = min(ans,ask_min(l,r,R(p)));    update(p);    return ans;}long long n,m,a,b,c;string t;int main(){    memset(num,0,sizeof(num));    scanf("%lld",&n);    for(long long i = 1; i <= n; i ++)        scanf("%lld",&num[i]);    build(1,n,1);    scanf("%lld",&m);    for(long long i = 1; i <= m; i ++)    {        cin >> t;        if(t == "add")        {            scanf("%lld %lld %lld",&a,&b,&c);            change(a,b,1,c);        }        else if(t == "sum")        {            scanf("%lld %lld",&a,&b);            printf("%lld\n",ask_sum(a,b,1));        }        else if(t == "max")        {            scanf("%lld %lld",&a,&b);            printf("%lld\n",ask_max(a,b,1));        }        else if(t == "min")        {            scanf("%lld %lld",&a,&b);            printf("%lld\n",ask_min(a,b,1));        }    }    return 0;}

图论

货车运输

玛丽卡

1.最短路

floyd

void floyd(){    for(int k = 1; k <= n; k ++)        for(int i = 1; i <= n; i ++)            for(int j = 1; j <= n; j ++)                dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);}

spfa_slf

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int MAXN = 200005;int n,m,tot = 0,s,e,f,t,v;int first[MAXN],next[MAXN],dis[MAXN];bool use[MAXN];struct edge{    int f,t,v;}l[MAXN];void build(int f,int t,int v){    l[++ tot] = (edge){f,t,v};    next[tot] = first[f];    first[f] = tot;    return;}deque < int > q;void spfa(int s){    while(!q.empty()) q.pop_front();    memset(dis,0x3f,sizeof(dis));    memset(use,0,sizeof(use));    use[s] = true; dis[s] = 0;    q.push_back(s);    while(!q.empty())    {        int u = q.front();        q.pop_front();        use[u] = false;        for(int i = first[u]; i != -1; i = next[i])        {            int w = l[i].t;            if(dis[w] > dis[u] + l[i].v)            {                dis[w] = dis[u] + l[i].v;                if(!use[w])                {                    if(q.empty()) q.push_front(w);                    else if(dis[w] < dis[q.front()])                        q.push_front(w);                    else q.push_back(w);                    use[w] = true;//……                }            }        }    }    return;}int main(){    memset(first,0xff,sizeof(first));    scanf("%d %d %d %d",&n,&m,&s,&e);    for(int i = 1; i <= m ; i ++)    {        scanf("%d %d %d",&f,&t,&v);        build(f,t,v);build(t,f,v);    }    spfa(s);    printf("%d\n",dis[e]);    return 0;}

dij_heap

struct re{    int u,v;    bool operator < (const re &b)const    {        return v > b.v;    }};priority_queue < re > q;int dij(int s,int e){    memset(use,0,sizeof(use));    while(!q.empty())   q.pop();    q.push((re){s,0});    while(!q.empty())    {        re us = q.top();        q.pop();        int u = us.u;        if(u == e)  return us.v;        if(use[u])  continue;        use[u] = true;        for(int i = first[u]; i != -1; i = next[i])        {            int w = l[i].t;            int rs = us.v + l[i].v;            q.push((re){w,rs});        }    }    return -1;}

2.最小生成树

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 20005;int n,f,t,v,tot = 0;int fa[MAXN],deep[MAXN];struct edge{    int f,t,v;}l[MAXN];int find(int x){    return  x == fa[x] ? x : fa[x] = find(fa[x]);}bool same(int x,int y){    return find(x) == find(y);}bool cmp(edge a,edge b){    return a.v < b.v;}void init(){    memset(deep,0,sizeof(deep));    for(int i = 1; i <= n; i ++)        fa[i] = i;    return;}void merge(int x,int y){    x = find(x),y = find(y);    if(deep[x] > deep[y])   swap(x,y);    fa[x] = y;    if(deep[x] == deep[y]) deep[y] ++;    return;}int kru(){    int ans = 0;    sort(l + 1,l + tot + 1,cmp);    for(int i = 1; i <= tot; i ++)        if(!same(l[i].f,l[i].t))        {            ans += l[i].v;            merge(l[i].f,l[i].t);        }    return ans;}int main(){    memset(first,0xff,sizeof(first));    scanf("%d",&n);    init();    for(int i = 1; i <= n; i ++)        for(int j = 1; j <= n; j ++)        {            scanf("%d",&v);            if(i == j) continue;            tot ++;            l[tot].f = i,l[tot].t = j,l[tot].v = v;        }    printf("%d\n",kru());    return 0;   }

3.次短路

deque<int>q;void spfa_slf(int s){    memset(dis,0x3f,sizeof(dis));    memset(pre,0x3f,sizeof(pre));    memset(use,0,sizeof(use));    q.push_back(0);    q.push_back(s);    use[s] = true;    dis[s] = 0;    while(!q.empty())    {        int u = q.front();        q.pop_front();        use[u] = false;        for(int i = first[u];i != -1; i = next[i])        {            int w = l[i].t;            if(dis[w] > dis[u] + l[i].v)            {                pre[w] = dis[w];                dis[w] = dis[u] + l[i].v;                if(!use[w])                {                    if(q.empty()) q.push_front(w);                    else if(dis[w] < dis[q.front()])                        q.push_front(w);                    else    q.push_back(w);                    use[w] = true;                }            }//如果可以更新最短路,那么就让它更新吧//更新后的最短路是最短路,更新之前的最短路是当前的次短路            else if(pre[w] > dis[u] + l[i].v && dis[w] < dis[u] + l[i].v)            {                pre[w] = dis[u] + l[i].v;                if(!use[w])                {                    if(q.empty()) q.push_front(w);                    else if(dis[w] < dis[q.front()])                        q.push_front(w);                    else    q.push_back(w);                    use[w] = true;                }            }//如果不能更新最短路,但是可以更新次短路,那么就让它更新吧            else if(pre[w] > pre[u] + l[i].v)            {                pre[w] = pre[u] + l[i].v;                if(!use[w])                {                    if(q.empty()) q.push_front(w);                    else if(dis[w] < dis[q.front()])                        q.push_front(w);                    else    q.push_back(w);                    use[w] = true;                }            } //次短路可以更新次短路,那么就让它更新吧        }    }    return;}

4.K短路

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int MAXN = 200005;int first[MAXN],next[MAXN],tot = 0;int n,m,s,t,K,f,t,v;int h[MAXN],dis[MAXN];bool use[MAXN];struct edge{    int f,t,v;}l[MAXN];struct zt{    int u,v;    bool operator < (const int &b) const    {        return v + h[u] > b.v + h[b.u];    }};void build(int f,int t,int v){    l[++ tot] = (edge){f,t,v};    next[tot] = first[f];    first[f] = tot;    return;}priority_queue < zt > q;void dij(int s){    memset(dis,0x3f,sizeof(dis));    dis[s] = 0;q.push((zt){s,0});    while(!q.empty())    {        zt x = q.top(); p.pop();        int u = x.u;        for(int i = first[u]; i != -1; i = next[i])        {            int w = l[i].t;            if(dis[w] > dis[u] + l[i].v)            {                dis[w] = dis[u] + l[i].v;                q.push((zt){w,dis[w]});            }        }    }    return;}int dij_k(int s,int e,int k){    if(s == e) k ++;    q.push((zt){s,0});    while(!q.empty())    {        zt x = q.top();        int u = x.u;        q.pop();        if(u == e)        {            k --;            if(k == 0)                  return x.v;        }        for(int i = first[u]; i != -1; i = next[i])        {            int w = l[i].t;            int c = x.v + l[i].v;            q.push((zt){w,c});        }    }    return -1;}

5.LCA

void make_tree(int x,int f,int v){    deep[x] = deep[f] + 1;    fa[x][0] = f;rank[x] = v;    for(int i = first[x]; i != -1; i = next[i])        if(l[i].t != f) make_tree(l[i].t,x,v + l[i].v);    return;}void make_lca(){    for(int j = 1; j <= log2(n); j ++)        for(int i = 1; i <= n; i ++)            fa[i][j] = fa[fa[i][j - 1]][j - 1];    return;}int lca(int x,int y){    if(deep[x] < deep[y]) swap(x,y);    for(int i = log2(n); i >= 0; i --)        if(deep[fa[x][i]] >= deep[y])            x = fa[x][i];    if(x == y)  return x;    for(int i = log2(n); i >= 0; i --)        if(fa[x][i] != fa[y][i])            x = fa[x][i],y = fa[y][i];    return fa[x][0];}int main(){    memset(first,0xff,sizeof(first));    scanf("%d",&n);    for(int i = 1; i < n; i ++)    {        scanf("%d %d %d",&f,&t,&v);        build(f,t,v);        build(t,f,v);    }    make_tree(0,n,0);    make_lca();    scanf("%d",&m);    for(int i = 1; i <= m; i ++)    {        scanf("%d %d",&f,&t);        printf("%d\n",rank[f] + rank[t] - (rank[lca(f,t)] << 1));    }    return 0;}

6.二分图染色

queue < int > q;int work(int s){    while(!q.empty()) q.pop();    int cnt1 = 0,cnt2 = 0;    use[s] = true;    color[s] = 1;    q.push(s);    while(!q.empty())    {        int u = q.front();        q.pop();        if(color[u] == 1) cnt1 ++;        else    cnt2 ++;        for(int i = first[u]; i != -1; i = next[i])        {            int w = l[i].t;            if(!use[w])            {                color[w] = 1 - color[u];                use[w] = true;                q.push(w);            }            else                if(color[w] == color[u])                    return -1;        }    }    return ans += min(cnt1,cnt2);}

7.Tarjan

int first[MAXN],next[MAXN];int low[MAXN],dfn[MAXN];int scc_num,dfs_clock,scc[MAXN];stack < int > s;int dfs(int u){    low[u] = dfn[u] = ++ dfs_clock;    s.push(u);    for(int i = first[u]; i != -1; i = next[i])    {        int w = l[i].t;        if(!dfn[w])        {            dfs(w);            low[u] = min(low[w],low[u]);        }        else if(!scc[w])            low[u] = min(low[u],dfn[w]);    }    if(low[u] == dfn[u])    {        scc_num ++;        while(true)        {            int x = s.top();            s.pop();            scc[x] = scc_num;            if(x == u)  break;        }    }    return;}

8.dfs找环

void dfs(int x){    int k = x,cnt = 0;    while(true)    {        times[x] = cnt ++;        use[x] = k;        x = t[x];        if(use[x] > 0)        {            if(use[x] == k)            {                ans = min(ans,cnt - times[x]);                break;            }                   else            {                ans = ans;                break;            }           }    }}int main(){    memset(t,0,sizeof(t));    memset(use,0,sizeof(use));    scanf("%d",&n);    for(int i = 1; i <= n; i ++)        scanf("%d",&t[i]);    for(int i = 1; i <= n; i ++)        if(use[i] == 0)            dfs(i);    printf("%d\n",ans);    return 0;}

9.拓扑排序

void topsort(){    for(int i = 1; i <= n; i ++)        if(!rudu[i])   q.push(i);    while(!q.empty())    {        int u = q.front();        q.pop();        printf("%d ",u);        for(int i = first[i]; i != -1; i = next[i])        {            int w = l[i].t; rudu[w] --;            if(!rudu[w])  q.push(w);        }    }    return;} void init(){    scanf("%d",&n);    for(int i = 1; i <= n; i ++)    {        while(true)        {            scanf("%d",&x);            if(x == 0) break;            build(i,x); rudu[x] ++;        }    }    return;}

数论

int gcd(int a, int b){    // a > b    if(b == 0) return a;    return gcd(b,a % b);}int lcm(int x, int y){    int c;    c = x * y / gcd(x,y);    return c;}int exgcd(int a, int b, int &x, int &y){    // a > b    if(b == 0)     {        x = 1,y = 0;        return a;    }    int ans = gcd(b,a % b,x,y);    int w = x; x = y;    y = w - a / b * y;    return ans;}bool use[MAXN];void Eular_find_prime(){    for(int i = 2; i <= n; i ++)    {        if(use[i] == 0) prime[++ cnt] = i;        for(int j = 1; j <= cnt && prime[j] * i <= n; j ++)        {            use[prime[j] * i] = 1;            if(i % prime[j] == 0)   break;        }    }}void Erato_find_prime(){     for(int i = 2; i <= n; i ++)   if(!use[i])                 for(int j = i + i; j <= n; j += i)  use[j] = 1;    for(int i = 2; i <= n; i ++)        if(!use[i])     printf("%d ", i);    puts("");}int ksm(int a,int b){    if(b == 0)  return 1;    int ans = 1;    while(b)    {        if(b & 1)   ans *= a;        a *= a;b >>= 1;    }    return ans;}int FTA(int n)   //唯一分解定理 {          tot = 0;        for(int i = 2;i <= n;i ++)        {            while(n % i == 0)            {                num[tot ++] = i;                n /= i;            }        }        for(int i = 0;i < c;i ++)            printf(i == 0 ? "%d" : "*%d" ,num[i]);        puts("");    return 0;    }    

动态规划

背包

void zopack(int vi,int wi){    // 01背包     for(int i = v - vi; i >= 0; i --)        dp[i + vi] = max(dp[i + vi],dp[i] + wi);    return;}void wqpack(int vi,int wi){    //完全背包    for(int i = 0; i <= v - vi; i ++)        dp[i + vi] = max(dp[i + vi],dp[i] + wi);    return; }void dcpack(int vi,int wi,int num){    if(vi * num > v)    wqpack(vi,wi);    int k = 1;    while(k < num)    {        zopack(vi * k,wi * k);        num -= k;        k <<= 1;    }    zopack(vi * num,wi * num);    return;}int main(){    scanf("%d %d",&n,&v);    for(int i = 1; i <= n; i ++)    {        scanf("%d %d %d",&viv,&w,&num);        if(num < 0)     wqpack(viv,w);        else    dcpack(viv,w,num);    }    for(int i = 0; i <= v; i ++)        ans = max(ans,dp[i]);    printf("%d\n",ans);    return 0;} 

最长严格上升子序列

int where(int x){    /*        寻找x在g中的下标        即以x为最小结尾的子序列长度    */    int l = 1,r = n;    while(l <= r)    {        int mid = (l + r) >> 1;        if(g[mid] == x)            return mid;        else if(g[mid] < x)            l = mid + 1;        else if(g[mid] > x)            r = mid - 1;    }    return l;}int dpdpd(){    memset(g,0x3f,sizeof(g));//极大值     int len = 0;    /*        对于原序列中每一个数,寻找g中下标        并用这个数更新g数组与长度     */     for(int i = 1; i <= n; i ++)    {        int j = where(num[i]);        g[j] = min(g[j],num[i]);        len = max(len,j);    }    return len;}

石子归并

int main(){    memset(dp,0x3f,sizeof(dp));     scanf("%d",&n);    for(int i = 1; i <= n; i ++)    {        scanf("%d",&x);        sum[i] = sum[i - 1] + x;        dp[i][i] = 0;    }    for(int i = n - 1; i >= 1; i --)        for(int j = i + 1; j <= n; j ++)            for(int k = i; k <= j - 1; k ++)                dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);    printf("%d\n",dp[1][n]);    return 0;}

树形

没有上司的舞会

图上

伊吹萃香

环形

void dpdpd(){    memset(dp,0,sizeof(dp));    int k = n << 1;    for(int i = 2; i <= k; i ++)        for(int j = i - 1; j >= 1 && i - j < n; j --)            for(int r = j; r < i; r ++)                dp[j][i] = max(dp[j][i],dp[j][r] + dp[r + 1][i] + num[j] * num[r + 1] * num[i + 1]),ans = max(ans,dp[j][i]);    printf("%d\n",ans);}

套路QAQ

传纸条&&方格取数……
void dpdpd(){    for(int i = 1; i <= m ; i ++)        for(int j = 1; j <= n; j ++)            for(int x = 1; x <= m; x ++)                for(int y = 1; y <= n; y ++)                {                    if(i == x || j == y)                        dp[i][j][x][y] = max(max(dp[i - 1][j][x - 1][y],dp[i][j - 1][x][y - 1]),max(dp[i][j - 1][x - 1][y],dp[i - 1][j][x][y - 1])) + map[i][j];                    else                        dp[i][j][x][y] = max(max(dp[i - 1][j][x - 1][y],dp[i][j - 1][x][y - 1]),max(dp[i][j - 1][x - 1][y],dp[i - 1][j][x][y - 1])) + map[i][j] + map[x][y];                }}
拦截导弹
int main(){    memset(num,0,sizeof(num));    while(scanf("%d",&num[++ n]) != EOF);    //输入处理     n --;    for(int i = n - 1; i >= 0; i --)    {        for(int j = i; j <= n; j ++)            if(num[i] < num[j])                up[i] = max(up[i],up[j] + 1);        for(int j = i; j <= n; j ++)            if(num[i] > num[j])                down[i] = max(down[i],down[j] + 1);    }    for(int i = 0; i <= n; i ++)    {        maxs = max(up[i],maxs);        mins = max(down[i],mins);    }    printf("%d\n%d",mins + 1,maxs);    return 0;}
尼克的任务

输出第一个

void dpdpd(){    int xc = k;    for(int i = n; i >= 1; i --)    {        if(num[xc].l == i)//有>= 1的任务        {            while(num[xc].l == i)            {                if(dp[i] < dp[i + num[xc].t])                    dp[i] = dp[i + num[xc].t];                xc --;            }           }         else if(num[xc].l != i)//没有任务             dp[i] = dp[i + 1] + 1;    }
1 0