首页 > 代码库 > 【NOIP2014TG】solution

【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\n",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\n%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\n",ansn);
    for (register int i=1; i<=ansn; ++i) printf("%d\n",ans[i]);
}
int main(){init();solve();}

 

【NOIP2014TG】solution