zoukankan      html  css  js  c++  java
  • 2017ACM/ICPC广西邀请赛-重现赛

    这是在厚林工作室4个人打的一场

    骚呢

    两年没回去了

    这里写图片描述

    拿lzy的号打,打的被老刘查水表了

    这里写图片描述

    01

    枚举kkk15
    看到我的T就知道我是怎么wa的了。。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    ll powder(ll a,ll n){
        if(n==0) return 1ll;
        ll ret = powder(a,n/2);
        ret = ret * ret;
        if(n&1) return ret*a;
        return ret;
    }
    
    int main(){
        int T;
        ll n;
        while(cin>>n){
            int cnt = 0;
            for(ll i=1;i<=15;i++){
                if(powder(i,i)<=n)
                    cnt++;
            }
            cout<<cnt<<endl;
        }
        return 0;
    }

    02 Color it

    线段树,按y排,存x坐标,维护min

    按x排存y坐标也行的,

    防止炸空间,可以离散化或者像我这样,用到哪建到哪,最多是nlogn的

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 1e6 + 7;
    
    bool getCol;
    
    struct segTree{
        #define val(x) tree[x].val
        #define lson tree[rt].lc, l, m
        #define rson tree[rt].rc, m+1, r
        static const int TREE_N = N * 3 + 3e5;
        struct node{
            int lc, rc, val;
        } tree[TREE_N];
        int tot, root[55];
    
        void build(){
            memset(tree, 0, sizeof(tree));
            memset(root, 0, sizeof(root));
              tot = 0;
        }
    
        //p: pos, v: val
        void add(int p, int v, int &rt, int l, int r){
            if (!rt) val(rt = ++tot) = v;
            val(rt) = min(val(rt), v);
            if (l == r) return;
            int m = (l + r) >> 1;
            if (p <= m) add(p, v, lson);
            else add(p, v, rson);
        }
    
        void query(int L, int R, int v, int rt, int l, int r){
            if(getCol || !rt) return;
            if(L <= l && r <= R){
                if(val(rt) <= v) getCol = 1; return;
            }
            int m = (l + r) >> 1;
            if (L <= m) query(L, R, v, lson);
            if (R >  m) query(L, R, v, rson);
        }
        #undef val(x)
        #undef lson
        #undef rson
    } T;
    
    int main(){
        //freopen("in.txt", "r", stdin);
        int op, x, y, c, L, R, X;
          T.build();
        for (; scanf("%d", &op) && op != 3;){
            if (op == 0) T.build();
            else if(op == 1){
                scanf("%d%d%d", &x, &y, &c);
                  T.add(y, x, T.root[c], 1, N);
            }else if(op == 2){
                scanf("%d%d%d", &X, &L, &R);
                  int ans = 0;
                  for(int i = 0; i <= 50; i++){
                    getCol = 0;
                    T.query(L, R, X, T.root[i], 1, N);
                    if (getCol) ans++;
                  }
                  printf("%d
    ",ans);
            }
        }
        return 0;
    }

    03

    统计有多少V=(A,B,C,D)E=(AB,BC,CD,DA,AC)
    考虑一个边作为对角线时,如果有K个点跟这个边的两个端点都相连,那么有C2K中方案。
    统计时,让条边记录在度数比较少的点处,减少枚举次数,每次将3个边一起算贡献。

    #include <bits/stdc++.h>
    
    #define mp make_pair
    
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100005;
    
    vector<pair<int,int> > e[maxn];
    
    int du[maxn],u,v,n,m;
    ll cnt[maxn<<2];
    struct node{
        int u,v;
    }info[maxn<<2];
    
    struct Node{
        int idi,idep;
        Node(){}
        Node(int _idi,int _idep){
            idi=_idi;
            idep=_idep;
        }
    }a[maxn<<2];
    
    int main(){    
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++)
                e[i].clear();
            memset(a,0,sizeof a);
            memset(du,0,sizeof du);
            for(int i=1;i<=m;i++){
                scanf("%d%d",&u,&v);
                du[u]++;du[v]++;
                info[i].u=u;
                info[i].v=v;
            }
            for(int i=1;i<=m;i++){
                u=info[i].u;v=info[i].v;
                if(du[u] < du[v] || (du[u] == du[v] && u < v))
                    e[u].push_back(mp(v,i));
                else e[v].push_back(mp(u,i));
            }
            memset(cnt,0,sizeof cnt);
            for(int i=1;i<=m;i++){
                u=info[i].u;v=info[i].v;
                for(auto ep:e[u]) a[ep.first]=Node(i,ep.second);
                for(auto ep:e[v]){
                    if(a[ep.first].idi==i){
                        cnt[i]++;
                        cnt[ep.second]++;
                        cnt[a[ep.first].idep]++;
                    }
                }
            }
            ll res = 0;
            for(int i=1;i<=m;i++)
                res += (cnt[i]-1ll)*cnt[i]/2ll;
            printf("%lld
    ",res);
        }
        return 0;
    } 

    04

    Number of domino tilings of 4 X (n-1) board. 
    

    an=an1+5an2+an3an4,直接用杜教板子。。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <map>
    #include <set>
    #include <cassert>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const ll mod=1000000007;
    ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    // head
    
    int _;
    ll n;
    namespace linear_seq {
        const int N=10010;
        ll res[N],base[N],_c[N],_md[N];
    
        vector<ll> Md;
        void mul(ll *a,ll *b,ll k) {
            rep(i,0,k+k) _c[i]=0;
            rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
            for (int i=k+k-1;i>=k;i--) if (_c[i])
                rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
            rep(i,0,k) a[i]=_c[i];
        }
        int solve(ll n,VI a,VI b) { 
            ll ans=0,pnt=0;
            ll k=SZ(a);
            assert(SZ(a)==SZ(b));
            rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
            Md.clear();
            rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
            rep(i,0,k) res[i]=base[i]=0;
            res[0]=1;
            while ((1ll<<pnt)<=n) pnt++;
            for (int p=pnt;p>=0;p--) {
                mul(res,res,k);
                if ((n>>p)&1) {
                    for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                    rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
                }
            }
            rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
            if (ans<0) ans+=mod;
            return ans;
        }
        VI BM(VI s) {
            VI C(1,1),B(1,1);
            int L=0,m=1,b=1;
            rep(n,0,SZ(s)) {
                ll d=0;
                rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
                if (d==0) ++m;
                else if (2*L<=n) {
                    VI T=C;
                    ll c=mod-d*powmod(b,mod-2)%mod;
                    while (SZ(C)<SZ(B)+m) C.pb(0);
                    rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                    L=n+1-L; B=T; b=d; m=1;
                } else {
                    ll c=mod-d*powmod(b,mod-2)%mod;
                    while (SZ(C)<SZ(B)+m) C.pb(0);
                    rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                    ++m;
                }
            }
            return C;
        }
        int gao(VI a,ll n) {
            VI c=BM(a);
            c.erase(c.begin());
            rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
            return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
        }
    };
    
    int main() {
        while(~scanf("%lld",&n)){
            printf("%d
    ",linear_seq::gao(VI{1,1, 5, 11, 36, 95, 281, 781, 2245, 6336, 18061, 51205, 145601, 413351, 1174500, 3335651, 9475901, 26915305, 76455961, 217172736},n));
        }
    }

    05

    求三种sum丢掉第k位

    预处理出所有的前缀和后缀

    黑康说:按位枚举???

    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int N = 1e5 + 7;
    int arr[N];
    int prXor[N], prAnd[N], preOr[N];
    int suXor[N], suAnd[N], sufOr[N];
    
    int main(){
        //freopen("in.txt", "r", stdin);
        int n, q;
        for (; ~scanf("%d%d", &n, &q);){
            prXor[0] = suXor[n+1] = 0;
            prAnd[0] = suAnd[n+1] = ~0;
            preOr[0] = sufOr[n+1] = 0;
    
            //printf("%d
    ", prAnd[0]);
    
            for (int i = 1; i <= n; i++){
                scanf("%d", &arr[i]);
                prXor[i] = prXor[i-1] ^ arr[i];
                prAnd[i] = prAnd[i-1] & arr[i];
                preOr[i] = preOr[i-1] | arr[i];
            }
            for (int i = n; i >= 1; i--){
                suXor[i] = suXor[i+1] ^ arr[i];
                suAnd[i] = suAnd[i+1] & arr[i];
                sufOr[i] = sufOr[i+1] | arr[i];
            }
            for (int k; q--;){
                scanf("%d", &k);
                int ansXor = prXor[k-1] ^ suXor[k+1];
                int ansAnd = prAnd[k-1] & suAnd[k+1];
                int ansOrr = preOr[k-1] | sufOr[k+1];
                printf("%d %d %d
    ", ansAnd, ansOrr, ansXor);
            }
        }    
        return 0;
    }

    06

    好像是个傻逼题,然后犯了傻逼错误

    贡献了-6的罚时,

    国王的坐标给的那么恶心的数字,就是告诉你,国王不会在wall上,然后要让国王能到达任意地方,就要让这些wall无法形成环就可以了,所以,不是环,树嘛,要求删去的最少,求个最大生成树,然后ans=sumallsumtree

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define fi first
    #define se second
    using namespace std;
    typedef pair<int, int> P;
    const int N = 1e5 + 7;
    
    struct Edge{
        int from,to,w;
        Edge(){}
        Edge(int x,int y,int z):from(x),to(y),w(z){}
        bool operator < (const Edge& a) const{return w > a.w;}
    } edges[N * 2];
    
    int f[N];
    int F(int x){return f[x]==x ? x : (f[x]=F(f[x]));}
    
    bool vis[N];
    P kruskal(int n, int m){
        int treenum = n; //forests    
        for (int i = 1;i <= n; i++) f[i] = i;
        sort(edges, edges + m);
        int cnt = 0, ans = 0;
        for (int i = 0; i < m; i++){
            Edge &e = edges[i];
            if (F(e.from) == F(e.to)) continue;
            f[F(e.from)] = F(e.to);
            treenum--;
            ans += e.w;
        }
        return P(treenum, ans);
    }
    
    int main(){
        //freopen("in.txt", "r", stdin);
        int n, x, y, u, v, c, m;
        for (; scanf("%d%d", &n, &m)==2;){
            for (int i = 1; i <= n; i++) scanf("%d%d", &x, &y);
            int all = 0;
            for (int i = 0; i < m; i++){
                scanf("%d%d%d", &u, &v, &c);
                edges[i] = Edge(u, v, c);
                all += c;
            }
            P p = kruskal(n, m);
            printf("%d %d
    ", m-(n-p.fi), all - p.se);
        }
        return 0;
    }

    07毛对子和毛顺子

    贪心:取i,i-1,i-2这个顺子的时候先把i-1,i-2的对子取掉,取完再取i的对子

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int a[1000005],x,n;
    
    int main(){
        while(~scanf("%d",&n)){
            memset(a,0,sizeof a);
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                a[x]++;
            }
            int cnt = 0;
            for(int i=1;i<=1000000;i++){
                if(i>=3)
                    if(a[i] && a[i-1] && a[i-2]){
                        a[i]--;a[i-1]--;a[i-2]--;
                        cnt++; 
                    }
                cnt += a[i]/2;
                a[i] %= 2;
            }
            printf("%d
    ",cnt);
        }
        return 0;
    } 

    08

    开始打表的时候发现如果a是奇数的时候肯定是1

    然后a是偶数的时候,2的因子个数很多,枚举一下就行了,后面的就为0了。

    开始打表发现,an的时候,几乎是所有的偶数,无脑了几发。发现a<n的时候答案不对。事实上,枚举一下较小的部分。加上后面0的部分。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    ll n,a;
    
    ll power(ll a,ll b,ll mod){
        if(b==0) return 1ll;
        ll ret = power(a,b/2,mod);
        ret = ret * ret % mod;
        if(b&1)
            return ret*a%mod;
        return ret;
    }
    
    ll up(ll n,ll a){
        return (n + a - 1) / a;
    }
    
    int main(){
        //freopen("output.txt","w",stdout);
        while(~scanf("%lld%lld",&n,&a)){
            if(a&1){
                puts("1");
                continue;
            }
            ll mod = 1ll<<n; 
            ll res = 0;
            for(int i=2;i<=n;i+=2)
                if(power(a,i,mod) == power(i,a,mod)) res++;
            res += (1<<n) >> (up(n,a));
            res -= n >> (up(n,a));
            printf("%d
    ",res);
        }
        return 0;
    } 

    10

    【bzoj3261】最大异或和
    首先,如果是区间异或的话,可以用可持续化Trie树。对于树上的可以用dfs序做。查询就查询in[u]到out[u]的的区间就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define ll long long 
    #define N 200005
    #define inf 2000000000
    using namespace std;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        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 bin[30];
    int n,m;
    int a[N],b[N],root[N];
    struct trie{
        int cnt;
        int ch[N*30][2],sum[N*30];
        void init(){
            cnt = 0;
            memset(ch,0,sizeof ch);
            memset(sum,0,sizeof sum);
        }
        int insert(int x,int val){
            int tmp,y;tmp=y=++cnt;
            for(int i=29;i>=0;i--)
            {
                ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
                sum[y]=sum[x]+1;
                int t=val&bin[i];t>>=i;
                x=ch[x][t];
                ch[y][t]=++cnt;
                y=ch[y][t];
            }
            sum[y]=sum[x]+1;
            return tmp;
        }
        int query(int l,int r,int val){
            int tmp=0;
            for(int i=29;i>=0;i--)
            {
                int t=val&bin[i];t>>=i;
                if(sum[ch[r][t^1]]-sum[ch[l][t^1]])
                    tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
                else r=ch[r][t],l=ch[l][t];
            }
            return tmp;
        }
    }trie;
    
    int in[N],out[N],cnt;
    
    vector<int> e[N];
    
    void dfs(int id,int fa){
        in[id] = ++cnt;
        root[cnt] = trie.insert(root[cnt-1],a[id]);
        for(auto ep:e[id]){
            if(ep == fa) continue;
            dfs(ep,id);
        }
        out[id]=cnt;
    }
    
    int main(){
        bin[0]=1;for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++) e[i].clear();
            for(int i=1;i<=n;i++)a[i]=read();
            for(int i=2;i<=n;i++){
                int v; 
                scanf("%d",&v);
                e[v].push_back(i);
            }
            cnt=0;
            trie.init(); 
            dfs(1,0);
            int u,x;
            //for(int i=1;i<=n;i++){
            //    printf("in[%d],out[%d] %d
    ",in[i],out[i],i);
            //}
            //cout<<root[4]<<endl; 
            while(m--){
                scanf("%d%d",&u,&x);
                printf("%d
    ",trie.query(root[in[u]-1],root[out[u]],x));
            }
        }
        return 0;
    }

    哇哦

    这里写图片描述

    这里写图片描述

  • 相关阅读:
    node md5
    Iptables入门教程
    centos 6.5 yum安装lnmp
    SSH日志位置
    【收藏】实战Nginx与PHP(FastCGI)的安装、配置与优化
    读《微博春晚背后的技术故事》笔记
    下载整个网页的方法,包括样式、图片、和js
    【收藏】下载Chrome商店插件的方法,万恶的gwd
    nginx变量
    【收藏】SSH原理与运用
  • 原文地址:https://www.cnblogs.com/cww97/p/7533936.html
Copyright © 2011-2022 走看看