zoukankan      html  css  js  c++  java
  • NOIP2012 提高组合集

    NOIP 2012 提高组 合集

    D1 T1 Vigenère 密码

    模拟题,观察到两个数对应位置-1相加的和%26就是对应的字母,按照这个性质模拟即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    char frm1[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
    char frm2[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    int calc(char c)
    {
        if(c>='a'&&c<='z') return c-'a';
        return c-'A';
    }
    char s1[2010],s2[110],s3[2010];
    int main()
    {
        scanf("%s%s",s2+1,s1+1);
        int k1=strlen(s1+1),k2=strlen(s2+1),k3=0;
        int cnt=k1/k2+((k1%k2==0)?0:1);
        // printf("Shit %d
    ",cnt);
        for(int i=1;i<=cnt;i++)
        {
            for(int j=1;j<=k2;j++) s3[++k3]=s2[j];
        }
        // printf("%s
    %s
    ",s1+1,s3+1);
        // for(int i=0;i<=25;i++) cout << calc(frm2[i]) << " " ;
        for(int i=1;i<=k1;i++)
        {
            int x1=calc(s1[i]),x2=calc(s3[i]);
            char c;
            if(s1[i]>='a'&&s1[i]<='z') c=frm2[(x1+26-x2)%26];
            else c=frm1[(x1+26-x2)%26];
            // puts("Fuck");
            putchar(c);
            // cout << s1[i] << s3[i] << (x1+x2)%26 << " " << x1+x2 << " " << c << endl ;
        }
        return 0;
    }
    

    D1 T2 国王游戏

    通过简单的小推导我们可以发现自己的$a_i*b_i$越大的越靠后越优,然后开心之余发现这个题的考点是高精度... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010 
    int n,l=1,a[N],b[N],c[N],g[N*10];
    using namespace std;
    void dispose1(int x)
    {
        for(int i=1;i<=l;i++) g[i]*=b[x];
        for(int i=1;i<=l;i++)
        {
            g[i+1]+=(g[i]/10);
            g[i]%=10;
        }
        l++;
        while(g[l]>9)
        {
            g[l+1]+=(g[l]/10);
            g[l]%=10;
            l++;
        }
        if(g[l]==0) l--;
    }
    void dispose2()
    {
        for(int i=l;i>=1;i--)
        {
            g[i-1]+=((g[i]%c[n])*10);
            g[i]/=c[n];
        }
        while(g[l]==0) l--;
        if(l==0) puts("1");
    }
    void qsort(int l,int r)
    {
        int i=l,j=r,mid=a[(l+r)/2];
        while(i<=j)
        {
            while(a[i]<mid) i++;
            while(a[j]>mid) j--;
            if(i<=j)
            {
                int t=a[i]; a[i]=a[j]; a[j]=t;
                t=b[i]; b[i]=b[j]; b[j]=t;
                t=c[i]; c[i]=a[j]; c[j]=t;
                i++; j--;
            }
        }
        if(l<j) qsort(l,j);
        if(i<r) qsort(i,r);
    }
    int main()
    {
        scanf("%d",&n);
        scanf("%d %d",&b[0],&c[0]);
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&b[i],&c[i]);
            a[i]=b[i]*c[i];
        }
        qsort(1,n);
        g[1]=b[0];
        for(int i=1;i<n;i++) dispose1(i);
        dispose2();
        for(int i=l;i>=1;i--) printf("%d",g[i]);
        return 0;
    }
    

    D1 T3 开车旅行

    一眼dp题。

    状态:dp[i][j][k],表示从i开始走了2^j步,第k个人走了多少。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #define N 100005
    #define INF 10000000000000ll
    using namespace std;
    int n,starx,height[N],f[N][20][5],dp1[N][20][3],dp2[N][20][3];
    struct Node
    {
        int idx,data;
        friend bool operator<(const Node &a,const Node &b) {return a.data<b.data;}
    };
    multiset<Node>s;
    void calc(int S,int &a,int &b,int x)
    {
        int now=S;
        for(int k=18;~k;k--)
        {
            if(f[now][k][0]&&a+b+dp1[now][k][0]+dp2[now][k][0]<=x)
            {
                a+=dp1[now][k][0];
                b+=dp2[now][k][0];
                now=f[now][k][0];
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&height[i]);
        Node a;
        height[0]=2e9;height[n+1]=-2e9;
        a.idx=0;a.data=2e9;s.insert(a);s.insert(a);
        a.idx=n+1;a.data=-2e9;s.insert(a);s.insert(a);
        for(int i=n;i;i--)
        {
            int goa,gob; Node aa;
            aa.idx=i,aa.data=height[i];
            s.insert(aa);
            set<Node>::iterator it=s.lower_bound(aa);
            int pre,nxt;
            int preh,nxth;
            it++; nxt=(*it).idx; nxth=(*it).data;
            it--;it--; pre=(*it).idx; preh=(*it).data;
            it++;
            if(abs(nxth-height[i])>=abs(preh-height[i]))
            {
                gob=pre;
                it--;it--;
                if(abs(nxth-height[i])>=abs((*it).data-height[i])) goa=(*it).idx;
                else goa=nxt;
            }
            else
            {
                gob=nxt;
                it++;it++;
                if(abs(preh-height[i])>abs((*it).data-height[i])) goa=(*it).idx;
                else goa=pre;
            }
            f[i][0][0]=goa;
            f[i][0][1]=gob;
            dp1[i][0][0]=abs(height[i]-height[goa]);
            dp1[i][1][0]=dp1[i][0][0];
            dp2[i][0][1]=abs(height[i]-height[gob]);
            dp2[i][1][1]=dp2[i][0][1];
            
        }
        for(int i=1;i<=n;i++)
        {
            f[i][1][0]=f[f[i][0][0]][0][1];
            dp1[i][1][0]=dp1[i][0][0];
            dp2[i][1][0]=abs(height[f[i][1][0]]-height[f[i][0][0]]);
            f[i][1][1]=f[f[i][0][1]][0][0];
            dp2[i][1][1]=dp2[i][0][1];
            dp1[i][1][1]=abs(height[f[i][1][1]]-height[f[i][0][1]]);    
        }
        for(int k=2;k<=18;k++)
        {
            for(int i=1;i<=n;i++)
            {
                f[i][k][1]=f[f[i][k-1][1]][k-1][1];
                dp2[i][k][1]=dp2[f[i][k-1][1]][k-1][1]+dp2[i][k-1][1];
                dp1[i][k][1]=dp1[i][k-1][1]+dp1[f[i][k-1][1]][k-1][1];
                f[i][k][0]=f[f[i][k-1][0]][k-1][0];
                dp1[i][k][0]=dp1[i][k-1][0]+dp1[f[i][k-1][0]][k-1][0];
                dp2[i][k][0]=dp2[i][k-1][0]+dp2[f[i][k-1][0]][k-1][0];
            }
        }
        scanf("%d",&starx);
        double ans=INF*10.0;
        int idx;
        for(int i=1;i<=n;i++)
        {
            int la=0,lb=0;
            calc(i,la,lb,starx);
            if(!lb)
            {
                if(ans>INF) ans=INF,idx=i;
                else if(ans==INF&&height[idx]<height[i]) idx=i;
            }
            else
            {
                double now=(double)la/(double)lb;
                if(now<ans) ans=now,idx=i;
                else if(now==ans&&height[idx]<height[i]) idx=i;
            }
        }
        printf("%d
    ",idx);
        int cases;
        scanf("%d",&cases);
        while(cases--)
        {
            int a,b;
            int la=0,lb=0;
            scanf("%d%d",&a,&b);
            calc(a,la,lb,b);
            printf("%d %d
    ",la,lb);
        }
        return 0;
    }
    

    D2 T1 同余方程

    exgcd裸题。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    void exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(!b) x=1,y=0;
        else
        {
            exgcd(b,a%b,y,x);
            y-=(a/b)*x;
        }
    }
    int main()
    {
        ll a,b; cin >> a >> b ;
        ll x,y; exgcd(a,b,x,y);
        ll d=__gcd(a,b);
        x=(x%b/d+b/d)%b/d;
        cout << x << endl ;
    }
    

    D2 T2 借教室

    线段树大法好,$10^6$开始没想到nlogn能过,数组没开够。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define lson pos<<1
    #define rson pos<<1|1
    #define N 1000010 
    using namespace std; int tag[N<<2],minn[N<<2],a[N];
    inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
    int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
    inline void pushup(int pos) {minn[pos]=min(minn[lson],minn[rson]);}
    inline void pushdown(int pos)
    {
        if(!tag[pos]) return;
        minn[lson]+=tag[pos]; tag[lson]+=tag[pos];
        minn[rson]+=tag[pos]; tag[rson]+=tag[pos];
        tag[pos]=0;
    }
    void build(int l,int r,int pos)
    {
        if(l==r) {minn[pos]=a[l]; return;}
        int mid=(l+r)>>1;
        build(l,mid,lson); build(mid+1,r,rson);
        pushup(pos);
    }
    void update(int x,int y,int val,int l,int r,int pos)
    {
        if(x<=l&&r<=y) {minn[pos]-=val; tag[pos]-=val; return;}
        pushdown(pos); int mid=(l+r)>>1;
        if(x<=mid) update(x,y,val,l,mid,lson);
        if(mid<y) update(x,y,val,mid+1,r,rson);
        pushup(pos);
    }
    int query(int x,int y,int l,int r,int pos)
    {
        if(x<=l&&r<=y) return minn[pos];
        pushdown(pos); int mid=(l+r)>>1,ans=0x7f7f7f7f;
        if(x<=mid) ans=min(ans,query(x,y,l,mid,lson));
        if(mid<y) ans=min(ans,query(x,y,mid+1,r,rson));
        return ans;
    }
    int main()
    {
        int n=rd(),m=rd(); for(int i=1;i<=n;i++) a[i]=rd(); build(1,n,1);
        for(int s,t,v,i=1;i<=m;i++)
        {
            v=rd(),s=rd(),t=rd();
            if(query(s,t,1,n,1)<v) {printf("-1
    %d
    ",i); return 0;}
            update(s,t,v,1,n,1);
        }
        puts("0");
        return 0;
    }
    

    D2 T3 疫情控制

    先二分每个军队往上走多少。显然在没有到达根节点之前越往上越优。如果军队可以到达根节点判断这个军队可不可以上去然后原路返回,如果不可以显然是停留在原地更优,反之都移动到根节点上单独考虑。

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <ctime>
    #include <cstring>
    #include <algorithm>
    #define N 50005
    using namespace std;
    typedef long long ll;
    int n,m;
    struct E{
        int to,nxt;
        ll d;
    }b[N*2];
    int fst[N],tot;
    void add(int f,int t,ll d)
    {
        b[++tot]=(E){t,fst[f],d};fst[f]=tot;
        b[++tot]=(E){f,fst[t],d};fst[t]=tot;
    }
    ll dis[N];
    int fa[N][20];
    int top[N];
    int pe[N];
    bool cmp(int a,int b)
    {
        if(dis[a]!=dis[b])
            return dis[a]>dis[b];
        return a<b;
    }
    bool isf[N];
    int sz[N];
    void dfs(int x,int p)
    {
        top[x]=p;
        for(int i=1;i<=16;i++)
            fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=fst[x];i;i=b[i].nxt)
        {
            int v=b[i].to;
            if(!fa[v][0])
            {
                fa[v][0]=x;
                dis[v]=dis[x]+b[i].d;
                dfs(v,p);sz[x]++;
            }
        }
        if(!sz[x])isf[x]=true;
    }
    bool vis[N];
    int nd[N],C;
    queue<int> Q;
    void bfs(ll mid)
    {
        Q.push(1);C=0;vis[1]=1;
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            for(int i=fst[u];i;i=b[i].nxt)
            {
                int v=b[i].to;
                if(!vis[v])
                {
                    if(isf[v])
                        nd[++C]=top[v];
                    else Q.push(v);
                    vis[v]=1;
                }
            }
        }
        sort(nd+1,nd+C+1,cmp);
        C=unique(nd+1,nd+C+1)-nd-1;
    }
    ll stack[N];int Top;
    bool check(ll mid)
    {
        memset(vis,0,sizeof(vis));Top=0;
        for(int i=1;i<=m;i++)
        {
            int u=pe[i];int v=top[u];
            ll cst=dis[u]-dis[v];
            if(vis[v]||dis[u]+dis[v]<=mid)
            {
                ll p=mid-dis[u];
                stack[++Top]=p;
            }
            else if(cst<=mid)vis[v]=1;
            else
            {
                int p=u;ll res=mid;
                for(int j=16;j>=0;j--)
                {
                    int w=fa[p][j];
                    ll wv=dis[p]-dis[w];
                    if(wv<=res){p=w;res-=wv;}
                }
                while(sz[fa[p][0]]==1&&!vis[p]) 
                    vis[p]=1,p=fa[p][0];
                vis[p]=1;
            }
        }
        bfs(mid);
        int H=1;
        for(int i=C;i>=1;i--)
        {
            ll p=dis[nd[i]];
            while(stack[H]<p&&H<=Top)H++;
            if(H>Top) return false;H++;
        }
        return true;
    }
    int main()
    {
        scanf("%d",&n);
        int u,v;ll d;
        int cnt=0;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%lld",&u,&v,&d);
            add(u,v,d);
            if(u==1||v==1) cnt++;
        }
        for(int i=0;i<=18;i++)fa[1][i]=1;
        for(int i=fst[1];i;i=b[i].nxt)
        {
            int v=b[i].to;
            dis[v]=b[i].d;
            fa[v][0]=1;
            dfs(v,v);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&pe[i]);
        sort(pe+1,pe+m+1,cmp);
        if(m<cnt)
        {
            puts("-1");
            return 0;
        }
        ll l=-1,r=1e9,mid;
        while(r-l>1)
        {
            mid=(l+r)>>1;
            if(check(mid)) r=mid;
            else l=mid;
        }
        cout << r << endl ;
    }
    
  • 相关阅读:
    IBM Minus One(water)
    约瑟夫问题的循环链表实现
    双向链表(差不多)
    单向链表的建立,插入,删除(复习一下)
    找新朋友(欧拉函数)
    验证角谷猜想(hd1279)
    Wolf and Rabbit(gcd)
    Big Number(大数)
    字串数(高精度组合数)
    寻找素数对(hd1262)
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9595328.html
Copyright © 2011-2022 走看看