• NOIP2014提高组 解题报告


    D1

    T1 生活大爆炸版石头剪刀布

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,na,nb,ans1,ans2;
     5 int a[201],b[201];
     6 inline int qread()
     7 {
     8     int x=0,j=1;
     9     char ch=getchar();
    10     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    11     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*j;
    13 }
    14 int main()
    15 {
    16     scanf("%d%d%d",&n,&na,&nb);
    17     for(int i=1;i<=na;i++)
    18         a[i]=qread();
    19     for(int i=1;i<=nb;i++)
    20         b[i]=qread();
    21     int tot=na,cnt=nb;
    22     int j=1;
    23     while(tot<=n)
    24     {
    25         if(j>na)j=1;
    26         a[++tot]=a[j++];
    27     }
    28     j=1;
    29     while(cnt<=n)
    30     {
    31         if(j>nb)j=1;
    32         b[++cnt]=b[j++];
    33     }
    34     for(int i=1;i<=n;i++)
    35     {
    36         if(a[i]==b[i])continue;
    37         if(a[i]==0)
    38             if(b[i]==2 || b[i]==3)ans1++;
    39             else ans2++;
    40         if(a[i]==1)
    41             if(b[i]==0 || b[i]==3)ans1++;
    42             else ans2++;
    43         if(a[i]==2)
    44             if(b[i]==1 || b[i]==4)ans1++;
    45             else ans2++;
    46         if(a[i]==3)
    47             if(b[i]==2 || b[i]==4)ans1++;
    48             else ans2++;
    49         if(a[i]==4)
    50             if(b[i]==0 || b[i]==1)ans1++;
    51             else ans2++;
    52     }
    53     printf("%d %d
    ",ans1,ans2);
    54     return 0;
    55 }
    View Code

    T2 联合权值

    70分的暴力

    枚举所有点,与其相连的点(距离为一)的相连的点(不包括自己 距离为二)。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int mod=10007;
     5 const int N=200001;
     6 struct node{
     7     int v,nxt;
     8 }e[N<<1];
     9 int n,maxn,sum,num;
    10 int w[N],head[N],fat[N];
    11 inline int qread()
    12 {
    13     int x=0,j=1;
    14     char ch=getchar();
    15     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    16     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    17     return x*j;
    18 }
    19 void Insert(int u,int v)
    20 {
    21     e[++num].v=v;
    22     e[num].nxt=head[u];
    23     head[u]=num;
    24 }
    25 void calc(int u)
    26 {
    27     for(int i=head[u];i;i=e[i].nxt)
    28     {
    29         int v=e[i].v;
    30         for(int j=head[v];j;j=e[j].nxt)
    31             if(u!=e[j].v)
    32             {
    33                 maxn=max(maxn,w[u]*w[e[j].v]);
    34                 sum+=w[u]*w[e[j].v];
    35                 sum%=mod;
    36             }
    37     }
    38 }
    39 int main()
    40 {
    41     scanf("%d",&n);
    42     int u,v;
    43     for(int i=1;i<=n-1;i++)
    44     {
    45         u=qread();v=qread();
    46         Insert(u,v);
    47         Insert(v,u);
    48     }
    49     for(int i=1;i<=n;i++)
    50         w[i]=qread();
    51     for(int i=1;i<=n;i++)
    52         calc(i);
    53     printf("%d %d",maxn,sum);
    54     return 0;
    55 }
    View Code

    正解

     1 //过一点的最大联合权值为经过该点的最大点权乘以次大点权 
     2 //过一点的联合权值和为经过该点的所有点的点权和的平方减去平方和 
     3 #include<iostream>
     4 #include<cstdio>
     5 using namespace std;
     6 const int mod=10007;
     7 const int N=200001;
     8 struct node{
     9     int v,nxt;
    10 }e[N<<1];
    11 int n,maxn,num,ans,max1,max2,tot;
    12 int w[N],head[N],fat[N];
    13 inline int qread()
    14 {
    15     int x=0,j=1;
    16     char ch=getchar();
    17     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    18     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    19     return x*j;
    20 }
    21 void Insert(int u,int v)
    22 {
    23     e[++num].v=v;
    24     e[num].nxt=head[u];
    25     head[u]=num;
    26 }
    27 int main()
    28 {
    29     //freopen("link.in","r",stdin);
    30     //freopen("link.out","w",stdout);
    31     scanf("%d",&n);
    32     int u,v;
    33     for(int i=1;i<=n-1;i++)
    34     {
    35         u=qread();v=qread();
    36         Insert(u,v);
    37         Insert(v,u);
    38     }
    39     for(int i=1;i<=n;i++)
    40         w[i]=qread();
    41     for(int i=1;i<=n;i++)
    42     {
    43         max1=max2=num=tot=0;
    44         for(int j=head[i];j;j=e[j].nxt)
    45         {
    46             int v=e[j].v;
    47             if(w[v]>max2)
    48             {
    49                 max2=w[v];
    50                 if(max2>max1)swap(max2,max1);
    51             }
    52             tot=(tot+(w[v]*w[v])%mod)%mod;
    53             num=(num+w[v])%mod;
    54         }
    55         maxn=max(maxn,max1*max2);
    56         ans=(ans+(num*num-tot)%mod)%mod;
    57     }
    58     printf("%d %d",maxn,ans);
    59     //fclose(stdin);fclose(stdout);
    60     return 0;
    61 }
    View Code


    T3 飞扬的小鸟

    神奇的背包

     1 //在往上飞的时候是完全背包,往下掉的时候是01背包
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 const int INF=0x3f3f3f3f;
     7 const int N=10001;
     8 int n,m,k,ans=INF,tot;
     9 int up[N],down[N],topp[N],endd[N],f[N][1001];
    10 //f[i][j]表示到达第i行j高度时点击屏幕的最小次数 
    11 bool have[N];
    12 inline int qread()
    13 {
    14     int x=0,j=1;
    15     char ch=getchar();
    16     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    17     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    18     return x*j;
    19 }
    20 int Min(int a,int b)
    21 {
    22     if(a<b)return a;
    23     return b;
    24 }
    25 int main()
    26 {
    27 //    freopen("bird.in","r",stdin);
    28 //    freopen("bird.out","w",stdout);
    29     scanf("%d%d%d",&n,&m,&k);
    30     for(int i=0;i<=n-1;i++)
    31     {
    32         up[i]=qread();
    33         down[i]=qread();
    34     }
    35     for(int i=0;i<=n;i++)
    36         topp[i]=m+1;
    37     int x;
    38     for(int i=1;i<=k;i++)
    39     {
    40         x=qread();
    41         endd[x]=qread();topp[x]=qread();
    42         have[x]=1;
    43     }
    44     memset(f,0x3f,sizeof(f));
    45     for(int i=1;i<=m;i++)
    46         f[0][i]=0;//除第0列外的所有第0行次数都为零 
    47     for(int i=1;i<=n;i++)
    48     {
    49         for(int j=up[i-1];j<=m;j++)//上升 
    50         {
    51             f[i][j]=Min(f[i][j],Min(f[i-1][j-up[i-1]]+1,f[i][j-up[i-1]]+1));
    52             if(j==m)//特判,因为高度不超过m,所以有多种转移 
    53                 for(int l=m-up[i-1];l<=m;l++)
    54                     f[i][m]=Min(f[i][m],Min(f[i-1][l]+1,f[i][l]+1));
    55         }
    56         for(int j=endd[i]+1;j<=topp[i]-1;j++)//下降 
    57             if(j+down[i-1]<=m)
    58                 f[i][j]=Min(f[i][j],f[i-1][j+down[i-1]]);
    59         for(int j=1;j<=endd[i];j++)//考虑水管,去掉不合法解 
    60             f[i][j]=INF;
    61         for(int j=topp[i];j<=m;j++)
    62             f[i][j]=INF;
    63     }
    64     tot=k;
    65     for(int i=n;i;i--)
    66     {
    67         for(int j=endd[i]+1;j<=topp[i]-1;j++)
    68             ans=Min(ans,f[i][j]);
    69         if(ans!=INF)break;
    70         if(have[i])tot--;//有水管且未更新答案 
    71     }
    72     if(tot==k)printf("1
    %d
    ",ans);
    73     else printf("0
    %d
    ",tot);
    74     fclose(stdin);fclose(stdout);
    75     return 0;
    76 }
    View Code

    D2

    T1 无线网络发射器选址

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int d,n,ans,num;
     5 int a[150][150],x[21],y[21];
     6 inline int qread()
     7 {
     8     int x=0,j=1;
     9     char ch=getchar();
    10     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    11     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*j;
    13 }
    14 int main()
    15 {
    16 //    freopen("wireless.in","r",stdin);
    17 //    freopen("wireless.out","w",stdout);
    18     scanf("%d%d",&d,&n);
    19     for(int i=1;i<=n;i++)
    20     {
    21         x[i]=qread();y[i]=qread();
    22         a[x[i]][y[i]]=qread();
    23     }
    24     for(int i=0;i<=128;i++)
    25         for(int j=0;j<=128;j++)
    26         {
    27             int now=0;
    28             for(int k=1;k<=n;k++)
    29                 if(x[k]>=i-d && x[k]<=i+d && y[k]>=j-d && y[k]<=j+d)
    30                     now+=a[x[k]][y[k]];
    31             if(now==ans)num++;
    32             if(now>ans)
    33             {
    34                 ans=now;
    35                 num=1;
    36             }
    37         }
    38     printf("%d %d
    ",num,ans);
    39 //    fclose(stdin);fclose(stdout);
    40     return 0;
    41 }
    View Code

    T2 寻找道路

    如果想到反向bfs找能到达终点的点的话,这道题并不是很难做(我就没有想到Orz)

      1 //从终点反向建图bfs找能到达终点的点 
      2 //再正向建图SPFA求最短路 
      3 #include<iostream>
      4 #include<cstdio>
      5 #include<queue>
      6 #include<cstring>
      7 using namespace std;
      8 const int N=2e5+9;
      9 struct node{
     10     int v,nxt;
     11 }e[N];
     12 int n,m,s,t,Enum;
     13 int dis[10001],u[N],v[N],head[N];
     14 bool vis[10001];
     15 queue<int>q;
     16 inline int qread()
     17 {
     18     int x=0,j=1;
     19     char ch=getchar();
     20     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
     21     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     22     return x*j;
     23 }
     24 void Insert(int u,int v)
     25 {
     26     e[++Enum].v=v;
     27     e[Enum].nxt=head[u];
     28     head[u]=Enum;
     29 }
     30 void bfs1()
     31 //反向图中终点能到达的点在正向图中就能终点 
     32 //将其进行标记 
     33 {
     34     q.push(t);
     35     vis[t]=1;
     36     while(!q.empty())
     37     {
     38         int u=q.front();
     39         q.pop();
     40         for(int i=head[u];i;i=e[i].nxt)
     41         {
     42             int v=e[i].v;
     43             if(!vis[v])
     44             {
     45                 vis[v]=1;
     46                 q.push(v);
     47             }
     48         }
     49     }
     50 }
     51 bool check(int x)
     52 {
     53     for(int i=head[x];i;i=e[i].nxt)
     54         if(!vis[e[i].v])
     55             return 0;
     56     return 1;
     57 }
     58 bool SPFA()
     59 {
     60     q.push(s);
     61     dis[s]=0;
     62     while(!q.empty())
     63     {
     64         int u=q.front();
     65         q.pop();
     66         if(!check(u))continue;
     67         for(int i=head[u];i;i=e[i].nxt)
     68         {
     69             int v=e[i].v;
     70             if(!dis[v])
     71             {
     72                 dis[v]=dis[u]+1;
     73                 q.push(v);
     74                 if(v==t)
     75                 {
     76                     printf("%d
    ",dis[t]);
     77                     return 1;
     78                 }
     79             }
     80         }
     81     }
     82     return 0;
     83 }
     84 int main()
     85 {
     86     scanf("%d%d",&n,&m);
     87     for(int i=1;i<=m;i++)
     88     {
     89         u[i]=qread();v[i]=qread();
     90         if(u[i]!=v[i])//有自环 
     91             Insert(v[i],u[i]);//反向建图 
     92     }
     93     scanf("%d%d",&s,&t);
     94     bfs1();
     95     Enum=0;
     96     memset(head,0,sizeof(head));
     97     for(int i=1;i<=m;i++)
     98         if(u[i]!=v[i])
     99             Insert(u[i],v[i]);//正向建图找最短路 
    100     if(!vis[s])
    101     {
    102         printf("-1
    ");
    103         return 0;
    104     }
    105     if(!SPFA())printf("-1
    ");
    106     return 0;
    107 }
    View Code

    T3 解方程

    秦久韶算法

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int mod=1e9+7;
     5 int n,m,num;
     6 long long sum;
     7 int a[100001],ans[1000001];
     8 int qread()
     9 {
    10     long long x=0,j=1;
    11     char ch=getchar();
    12     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';x%=mod;ch=getchar();}
    14     return x*j;
    15 }
    16 bool calc(int x)
    17 {
    18     sum=0;
    19     for(int j=n;j>=0;j--)
    20         sum=((a[j]+sum)*x)%mod;
    21     if(!sum)return 1;
    22     return 0;
    23 }
    24 int main()
    25 {
    26 //    freopen("equation.in","r",stdin);
    27 //    freopen("equation.out","w",stdout);
    28     scanf("%d%d",&n,&m);
    29     for(int i=0;i<=n;i++)
    30         a[i]=qread();
    31     for(int i=1;i<=m;i++)
    32         if(calc(i))
    33             ans[++num]=i;
    34     printf("%d
    ",num);
    35     for(int i=1;i<=num;i++)
    36         printf("%d
    ",ans[i]);
    37 //    fclose(stdin);fclose(stdout);
    38     return 0;
    39 }
    View Code
  • 相关阅读:
    这些诗词你知道一句,却不知全诗!
    二十二、事件绑定及深入
    二十一、事件对象
    二十、事件入门
    十九、动态加载脚本和样式
    十八、DOM元素尺寸和位置
    十七、DOM操作表格及样式
    十六、DOM进阶
    十五、DOM基础
    正确使用volatile场景--状态标志
  • 原文地址:https://www.cnblogs.com/1078713946t/p/7677426.html
Copyright © 2020-2023  润新知