• 【解题报告】牡丹江现场赛之ABDIK ZOJ 3819 3820 3822 3827 3829


    那天在机房做的同步赛,比现场赛要慢了一小时开始,直播那边已经可以看到榜了,所以上来就知道A和I是水题,当时机房电脑出了点问题,就慢了好几分钟,12分钟才A掉第一题。。。

    A.Average Score

    题目大意:给定A序列和B序列,长度分别是n和m,告诉你A序列中的n-1个数和B序列的m个数,求剩下的那个A序列中的数满足:将这个数从A序列移除,然后添加到B序列,使得A序列的平均值变小,B序列的平均值变大。求这个数的取值范围(是整数)

    解题思路:求出A序列剩下的n-1个数的平均值,和B序列的平均值,答案就是这两个数之间的整数。

    解题代码:

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<string.h>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define FOR(i,n) for(i=0;i<(n);i++)
     7 #define CLR(a) memset(a,0,sizeof(a))
     8 #define CIN(a) scanf("%d",&a)
     9 using namespace std;
    10 int main()
    11 {
    12     int t,i;
    13     CIN(t);
    14     while(t--)
    15     {
    16         int n1,n2,s1=0,s2=0,a,b;
    17         CIN(n1);
    18         CIN(n2);
    19         for(i=1;i<n1;i++)
    20         {
    21             CIN(a);
    22             s1+=a;
    23         }
    24         for(i=0;i<n2;i++)
    25         {
    26             CIN(b);
    27             s2+=b;
    28         }
    29         if(s1%(n1-1)==0) s1=s1/(n1-1)-1;
    30         else s1=s1/(n1-1);
    31         s2=s2/n2+1;
    32         printf("%d %d
    ",s2,s1);
    33     }
    34     return 0;
    35 }
    View Code

    I.Information Entropy

    然后看I感觉很高大上的样子,看了好久没看懂,但是很多人做出来又不舍得放弃,于是就静下心来慢慢看,然后发现题目的意思大概就是把给的数据带入H(x)求答案就完了。。。但是如果出现P(xi)=0的情况的话就要用那个求极限的公式带,关于这个极限,由于把高数忘得一干二净,所以不知道怎么搞,后来用几何画板把函数图像画出来,发现那个值是0,然后就简单了。。。直接套公式。。

    代码:

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<string.h>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define FOR(i,n) for(i=0;i<(n);i++)
     7 #define CLR(a) memset(a,0,sizeof(a))
     8 #define CIN(a) scanf("%d",&a)
     9 using namespace std;
    10 int a[105];
    11 double (*f)(double) ;
    12 int main()
    13 {
    14     int t,i,x;
    15     char s[10];
    16     CIN(t);
    17     while(t--)
    18     {
    19         scanf("%d",&x);
    20         scanf("%s",s);
    21         for(i=0;i<x;i++)
    22         {
    23             scanf("%d",&a[i]);
    24         }
    25         if(strcmp(s,"bit")==0)
    26         {
    27             f=log2;
    28         }
    29         else if(strcmp(s,"nat")==0)
    30         {
    31             f=log;
    32         }
    33         else f=log10;
    34         double s=0;
    35         for(i=0;i<x;i++)
    36         {
    37             if(a[i]!=0) s+=((double)a[i]/100)*f((double)a[i]/100);
    38         }
    39         printf("%.12f
    ",-s);
    40     }
    41     return 0;
    42 }
    View Code

    D.Domination

    本着随波逐流的策略,就开始看过的人最多的D了。

    题目大意:给定一个N*M的网格,开始随机往里面放棋子,知道任意一行任意一列都有棋子为止,求已经放置的棋子数的期望。

    解题思路:概率DP,用dp[i][j][k]表示已经有i行,j列放过棋子,且总共放过k个棋子。对于某一状态,可以由四种状态扩展而来,可得状态转移方程:

    转移方程:

                        if(i!=n||j!=m)dp[i][j][k]+=(1.0*i*j-(k-1))/(m*n-(k-1))*dp[i][j][k-1];//这个if是判断出前一状态已经是终点状态则不能扩展
                        dp[i][j][k]+=(1.0*i*(m-(j-1)))/(m*n-k+1)*dp[i][j-1][k-1];
                        dp[i][j][k]+=(1.0*j*(n-i+1))/(m*n-k+1)*dp[i-1][j][k-1];
                        dp[i][j][k]+=((1.0*n-i+1)*(m-j+1))/(m*n-k+1)*dp[i-1][j-1][k-1];
    代码:
     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<string.h>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define FOR(i,n) for(i=0;i<(n);i++)
     7 #define CLR(a) memset(a,0,sizeof(a))
     8 #define CIN(a) scanf("%d",&a)
     9 using namespace std;
    10 double dp[51][51][2501];
    11 int main()
    12 {
    13     int t;
    14     int i,j,k,n,m;
    15     CIN(t);
    16     while(t--)
    17     {
    18         CIN(n);
    19         CIN(m);
    20         CLR(dp);
    21         dp[0][0][0]=1;
    22         for(i=1;i<=n;i++)
    23         {
    24             for(j=1;j<=m;j++)
    25             {
    26                 for(k=1;k<=(i*j);k++)
    27                 {
    28                     if(i!=n||j!=m)dp[i][j][k]+=(1.0*i*j-(k-1))/(m*n-(k-1))*dp[i][j][k-1];
    29                     dp[i][j][k]+=(1.0*i*(m-(j-1)))/(m*n-k+1)*dp[i][j-1][k-1];
    30                     dp[i][j][k]+=(1.0*j*(n-i+1))/(m*n-k+1)*dp[i-1][j][k-1];
    31                     dp[i][j][k]+=((1.0*n-i+1)*(m-j+1))/(m*n-k+1)*dp[i-1][j-1][k-1];
    32                     //printf("dp[%d][%d][%d]=%.12f
    ",i,j,k,dp[i][j][k]);
    33                 }
    34             }
    35         }
    36         double s=0;
    37         for(k=0;k<=(n*m);k++)
    38         {
    39             s+=(dp[n][m][k]*k);
    40         }
    41         printf("%.12f
    ",s);
    42     }
    43     return 0;
    44 }
    View Code

    做到这里的时候是4题都是1y,感觉自己屌屌的~

    B.Building Fire Stations

    这题题目读完在纸上画了半天,感觉会和最长链有关,于是大胆猜测是在最长链的四分分上,然后马上就否定了,后来感觉应该是先将整个树从最长链的中间拆开,再分别求最长链取中点。不会证明,但是又没有别的题可以搞,就直接按这个方法写了,然后数组开太小RE了一次,改了交就AC了。。Orz白错了一次。

    求树的最长链当时是第一次写,之前知道方法,但是没写过,没想到一次就过了。方法是先在树中随便取一点,遍历树找到距离这个点最远的点,然后这一点就是最长链的一个端点了,然后再从这个点遍历一次求出另一个端点就是最长链的另一点啦。

    关于断边,则直接用了一个标记即可。

    代码:

      1 #include<stdio.h>
      2 #include<math.h>
      3 #include<string.h>
      4 #include<iostream>
      5 #include<queue>
      6 #include<algorithm>
      7 #define FOR(i,n) for(i=0;i<(n);i++)
      8 #define CLR(a) memset(a,0,sizeof(a))
      9 #define CIN(a) scanf("%d",&a)
     10 using namespace std;
     11 #include<stdio.h>
     12 #include<string.h>
     13 #define point_MAX 200005
     14 #define edge_MAX 400005
     15 struct EDGE
     16 {
     17     int to;/*指向的点*/
     18     int next;/*指向的下一条邻边*/
     19     int w;/*权值*/
     20 }edge[edge_MAX];
     21 int len;/*边的数量*/
     22 int point[point_MAX];
     23 void init()/*初始化*/
     24 {
     25     len=0;
     26     memset(point,0,sizeof(point));
     27 }
     28 int add_edge(int a,int b,int w)/*添加由a指向b的权值为w的边*/
     29 {
     30     len++;
     31     edge[len].w=w;
     32     edge[len].to=b;
     33     edge[len].next=point[a];
     34     point[a]=len;
     35     return 0;/*无重边,插入*/
     36 }
     37 int del_edge(int a,int b)
     38 {
     39     int i;
     40     for(i=point[a];edge[i].to!=b;i=edge[i].next);
     41     edge[i].w=0;
     42 
     43     for(i=point[b];edge[i].to!=a;i=edge[i].next);
     44     edge[i].w=0;
     45 
     46     return 0;
     47 }
     48 int bo[200005];
     49 int road[200002];
     50 int zuiyuandian(int start)
     51 {
     52     int t,k,i;
     53     queue<int> q;
     54     CLR(bo);
     55     q.push(start);
     56     bo[start]=1;
     57     while(!q.empty())
     58     {
     59         //printf("l");
     60         k=q.front();
     61         q.pop();
     62 
     63         for(i=point[k];i;i=edge[i].next)
     64         {
     65             if(edge[i].w!=0)
     66                 if(bo[edge[i].to]==0)
     67                 {
     68                     q.push(edge[i].to);
     69                     road[edge[i].to]=k;
     70                     bo[edge[i].to]=1;
     71                 }
     72         }
     73     }
     74     return k;
     75 }
     76 int zuichang(int start)
     77 {
     78     int l,r,le,i;
     79     l=zuiyuandian(start);
     80     r=zuiyuandian(l);
     81     int len=0;
     82     for(i=r;i!=l;i=road[i]) {/*printf("%d->",i);*/len++;}
     83     len/=2;
     84     for(le=0,i=r;le<len;i=road[i],le++);
     85     int a=i,b=road[i];
     86 
     87     del_edge(a,b);
     88 
     89     l=zuiyuandian(a);
     90     r=zuiyuandian(l);
     91     len=0;
     92     for(i=r;i!=l;i=road[i]) len++;
     93     int ans1=len%2?len/2+1:len/2;
     94     len/=2;
     95     for(le=0,i=r;le<len;i=road[i],le++);
     96     a=i;
     97 
     98     l=zuiyuandian(b);
     99     r=zuiyuandian(l);
    100     len=0;
    101     for(i=r;i!=l;i=road[i]) len++;
    102     int ans2=len%2?len/2+1:len/2;
    103     len/=2;
    104     for(le=0,i=r;le<len;i=road[i],le++);
    105     b=i;
    106 
    107     printf("%d %d %d
    ",max(ans1,ans2),a,b);
    108 }
    109 int main()
    110 {
    111     int t,n,i;
    112     CIN(t);
    113     while(t--)
    114     {
    115         CIN(n);
    116         init();
    117         for(i=1;i<n;i++)
    118         {
    119             int a,b;
    120             CIN(a);
    121             CIN(b);
    122             add_edge(a,b,1);
    123             add_edge(b,a,1);
    124         }
    125     zuichang(1);
    126     }
    127     return 0;
    128 }
    View Code

    最后去搞H发现是一个模拟题,我想用map建立一棵树表示它然后查询但是超内存了Orz...一定是哪里姿势不够优美。。。SO,到最后也没搞出来,下次再搞了。

  • 相关阅读:
    C#实现清理系统内存
    WinForm 程序加管理员权限
    DataGridView 绑定List集合后实现自定义排序
    swfupload提示“错误302”的解决方法
    C# WinForm捕获全局异常
    C# WinForm应用程序降低系统内存占用方法
    清除webBrowser 缓存和Cookie的解决方案
    ThInkPHP加密和解密cookie(登录操作)
    prestashop 首页轮播幻灯片图片修改
    网页内容分享到微信
  • 原文地址:https://www.cnblogs.com/syiml/p/4032317.html
Copyright © 2020-2023  润新知