• 【NOIP2014TG】solution


    链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83|31

    D1T1(rps)

    题意:给你一个周期,以及胜负关系,求A和B的胜场。

    解题思路:暴力抄表,然后暴力计算即可。

    #include<cstdio> 
    #include<iostream> 
    using namespace std; 
    int a[201],na,nb,b[201],ansa,ansb,n; 
    int f[5][5]{{0,0,1,1,0},{1,0,0,1,0},{0,1,0,0,1},{0,0,1,0,1},{1,1,0,0,0}}; 
    int main(){ 
        cin>>n>>na>>nb; 
        for (int i=1; i<na; i++) 
            scanf("%d",&a[i]); 
        cin>>a[0]; 
        for (int i=1; i<nb; i++) 
            scanf("%d",&b[i]); 
        cin>>b[0]; 
        for (int i=1; i<=n; i++){ 
            ansa+=f[a[i%na]][b[i%nb]]; 
            ansb+=f[b[i%nb]][a[i%na]]; 
        } 
        cout<<ansa<<" "<<ansb;     
    } 

    D1T2(link)

    题意:给你棵树,求最大联合权值与联合权值和,(联合权值:距离为2的2个点的点权之积)

    解题思路:枚举所有中间点,暴力算出所有的与其相连的点权之和与其点权平方和,用数学公式求出乘积和,最大的较好做,不多解释。

    #include <stdio.h>
    #define MN 200005
    #define mod 10007
    #define ll long long
    #define v edge[j].to
    #define max(a,b) ((a)>(b)?(a):(b))
    int w[MN],head[MN],n,maxx,sum,cnt;
    struct zxy{
        int to,nxt;
    }edge[MN<<1];
    inline int in(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;}
    void init(){
        n=in();
        for (int i=1; i<n; ++i){
            register int x=in(),y=in();
            ins(x,y);ins(y,x);
        }
        for (register int i=1; i<=n; ++i) w[i]=in();
    }
    void solve(){
        for (register int i=1; i<=n; ++i){
            register ll tmp=0,tmpp=0;register int ma1=0,ma2=0;
            for (register int j=head[i]; j; j=edge[j].nxt){
                tmp+=w[v],tmpp+=w[v]*w[v],tmp%=mod,tmpp%=mod;
                if (w[v]>ma1) ma2=ma1,ma1=w[v];
                else ma2=max(ma2,w[v]);
            }
            maxx=max(maxx,ma1*ma2),sum+=tmp*tmp-tmpp;sum%=mod;
        }
        printf("%d %d
    ",maxx,sum);
    }
    int main(){init();solve();}

    D1T3(bird)

    题意:看题目吧= =就是flappy birds啊

    解题思路:每次点击看成一个费用为1,体积为X[i]的物品,反之则。。。。然后按题意跑一遍求最小费用的背包,注意对高度>m的特殊处理与管道的判断。

    #include <stdio.h>
    #include <string.h>
    #define MN 10005
    #define MM 1005
    #define inf 0x3f3f3f3f
    #define min(a,b) ((a)<(b)?(a):(b))
    int n,m,k,up[MN],down[MN],dp[2][MM],bot[MN],top[MN],ansn,ans;
    inline int in(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    void init(){
        n=in(),top[n]=m=in(),k=in();
        for (int i=0; i<n; ++i) top[i]=m,up[i]=in(),down[i]=in();
        for (register int i=1,s; i<=k; ++i) bot[s=in()]=in()+1,top[s]=in()-1;
    }
    void solve(){
        for (register int i=1; i<=n; ++i){
            memset(dp[i&1],0x3f,sizeof(dp[i&1]));
            register int minn=inf;
            for (register int j=up[i-1]+1; j<m; ++j)
                dp[i&1][j]=min(dp[i&1][j-up[i-1]]+1,min(dp[(i&1)^1][j-up[i-1]]+1,dp[i&1][j]));      
            for (register int j=m-up[i-1]; j<=m; ++j)
                dp[i&1][m]=min(dp[i&1][j]+1,min(dp[i&1][m],dp[(i&1)^1][j]+1));  
            for (register int j=down[i-1]+1; j<=m; ++j)
                dp[i&1][j-down[i-1]]=min(dp[(i&1)^1][j],dp[i&1][j-down[i-1]]);      
            for (register int j=0; j<bot[i]; ++j) dp[i&1][j]=inf;
            for (register int j=top[i]+1; j<=m; ++j) dp[i&1][j]=inf;
            for (register int j=bot[i]; j<=top[i]; ++j) minn=min(minn,dp[i&1][j]);
            if (minn==inf){
                puts("0");
                printf("%d",ansn);
                return;
            }
            if ((top[i]^m)&&(bot[i])) ++ansn;
        }ans=inf;
        for (register int j=1; j<=m; ++j)
            ans=min(ans,dp[n&1][j]);
        printf("1
    %d",ans);
    }
    int main(){init();solve();}

    D2T1(wireless)

    我写了傻逼做法,反正这题就是傻逼模拟。

    #include<stdio.h>
    #define MN 130
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    int f[MN][MN],n,d,ans[MN][MN],ma,summ;
    inline int in(){
        int x=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int main(){
        d=in();n=in();
        for (int i=1; i<=n; ++i){
            int x=in(),y=in(),l=in();
            f[x][y]=l;
        }
        for (register int i=0; i<129; ++i)
            for (register int j=0; j<129; ++j){
                for (register int a=max(0,i-d); a<=min(128,i+d); ++a)
                    for (register int b=max(0,j-d); b<=min(128,j+d); ++b)
                        ans[i][j]+=f[a][b];
                ma=max(ans[i][j],ma);
            }
        for (register int i=0; i<129; ++i)
            for (register int j=0; j<129; ++j)
                if (ma==ans[i][j]) summ++;
        printf("%d %d",summ,ma);
    }

    D2T2(road)

    题意:看题目吧= =。

    解题思路:首先建反边然后从终点bfs一遍,计算一下入度,然后判断一下是否可行,再正向bfs一遍即可。

    #include <stdio.h>
    #include <string.h>
    #define MN 10005
    #define ME 200005
    int head[MN],dis[MN],n,e,fb[MN],cnt,s,t,que[MN],du[MN],cntt[MN];
    bool vis[MN];
    struct zxy{
        int to,nxt;
    }edge[ME<<1];
    inline void ins(int x,int y,int *h){edge[++cnt].to=y,edge[cnt].nxt=h[x],h[x]=cnt;}
    inline int in(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x;
    }
    inline void bfs(int s,int *hd){
        int h=0,t=1;que[1]=s;
        memset(dis,127/3,sizeof(dis));
        dis[s]=0;vis[s]=1;
        while(h<t){
            for (register int i=hd[que[++h]]; i; i=edge[i].nxt){
                register int v=edge[i].to;++cntt[v];
                if (!vis[edge[i].to]){
                    dis[v]=dis[que[h]]+1;vis[v]=1;que[++t]=v;
                }
            }
        }
    }
    void init(){
        n=in(),e=in();
        for (register int i=1; i<=e; ++i){
            register int x=in(),y=in();++du[x];
            ins(x,y,head);ins(y,x,fb);
        }
        s=in(),t=in();
    }
    void solve(){
        bfs(t,fb);for (register int i=1; i<=n; ++i) vis[i]=du[i]!=cntt[i];
        bfs(s,head);if (!vis[t]){puts("-1");return;}
        printf("%d",dis[t]);
    }
    int main(){init();solve();return 0;}

    D2T3(equation)

    题意:看题目

    解题思路:大丧题,欺负我数学不好。我们考虑选取mo数,然后优化掉高精度操作,然后注意一下多个mo防止出现恰好为mo数倍数的解,多用几个10000左右的质数应该就比较稳了。

    #include <stdio.h>
    #define MN 105
    #define MM 1000005
    #define ML 10005
    const int mod[5]={10007,10009,10037,10039,10061};
    int a[5][MN],ans[MM],ansn,n,b[5][13005],m;char ch[ML];
    inline void check(int x){
        for (register int i=0; i<5; ++i)
            for (register int j=n; j>=0; --j)
            b[i][x%mod[i]]=(b[i][x%mod[i]]*(x%mod[i])+a[i][j])%mod[i];
    }
    inline bool judge(int x){
        for (register int i=0; i<5; ++i) if (b[i][x%mod[i]]) return 0;
        return 1;
    }
    void init(){
        scanf("%d%d",&n,&m);for (int i=0; i<=n; ++i){
            scanf("%s",ch);for (register int j=0; ch[j]; ++j)
                if (ch[j]>='0'&&ch[j]<='9')
                    for (register int k=0; k<5; ++k)
                        a[k][i]=(a[k][i]*10+ch[j]-'0')%mod[k];
            if (ch[0]=='-')
                for (register int k=0; k<5; ++k) a[k][i]*=-1;
        }
    }
    void solve(){
        for (register int i=0; i<10061; ++i) check(i);
        for (register int i=1; i<=m; ++i) if (judge(i)) ans[++ansn]=i;
        printf("%d
    ",ansn);
        for (register int i=1; i<=ansn; ++i) printf("%d
    ",ans[i]);
    }
    int main(){init();solve();}
  • 相关阅读:
    Linux curl使用简单介绍
    SecureCRT编码转换vim
    BigTable/HBase基本概念解读 & Hbase shell常用命令
    Crontab用法说明(Linux)
    Sina SSO 登陆过程分析
    浅谈队列
    搞怪的 log4net 记录日志 性能测试
    iBatis.Net异步多线程 操作Ibatis报错
    高并发高负载的大型网站系统架构
    [置顶] IIs Web 站点安全 监控 站点自动部署 重启
  • 原文地址:https://www.cnblogs.com/Melacau/p/NOIP2014TGsolution.html
Copyright © 2020-2023  润新知