zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第二场)

    传送门

    参考资料:

      [1]:官方题解(提取码:ar7y)

      [2]:标程(提取码:3qb2)

    A.Eddy Walker(概率+打表找规律)

    •题意

      有一个圆,圆上有 n 个点,编号为 0~n-1;

      初始,Eddy 处于 0 位置,每次他独立地均匀随机选择是向前(0+1)还是向后(0-1 = n-1)走;

      现给你 n,m ,让你求 Eddy 在走 n 步后停留在 m 处的概率;

      最终结果输出前缀积;

    •题解

      在补这道题前,补了补概率论的相关概念;

      1.频率定义

        若在相同的条件下进行的 n 次试验中,事件 A 发生了 m 次,则称比值 m / n 为事件 A 发生的频率;

      2.概率的统计定义

        在相同条件下进行大量重复试验,当试验次数充分大时,事件 A 的频率将在某个常数 p 附近摆动,
        这个常数 p 称为事件 A 的概率,记为 P(A);

      有了这些概念后,找了几篇博文看,发现,要么是达标找规律,要么就是直接写结论,没有严格的数学证明;

      哎,本蒟蒻太菜,并不擅长概率论方面的题,暂且补补打表找规律的;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mem(a,b) memset(a,b,sizeof(a))
     4 const int maxn=100;
     5 
     6 int n;
     7 bool vis[maxn];
     8 int k[maxn];
     9 
    10 int main()
    11 {
    12     srand((unsigned int)(time(NULL)));
    13 
    14     scanf("%d",&n);///n最好不要太大,不然,不能再有限的时间内跑出结果
    15     for(int i=1;i <= 100000;i++)
    16     {
    17         mem(vis,false);
    18         vis[0]=true;
    19 
    20         int cur=0;
    21         int t=1;
    22 
    23         while(t < n)
    24         {
    25             int x=rand()%2 ? 1:-1;///向前或向后走
    26             cur=(cur+x+n)%n;
    27 
    28             if(!vis[cur])
    29             {
    30                 vis[cur]=true;
    31                 t++;
    32             }
    33         }
    34         k[cur]++;
    35     }
    36     for(int i=1;i < n;i++)
    37         printf("%d ",k[i]);
    38     printf("
    ");
    39 
    40     return 0;
    41 }
    打表找规律

      当输入的 n = 10 时,大概可以看出除 0 外,其他位置的概率为 1 / (n-1);

      0 单独处理;

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int MOD=1e9+7;
     5 
     6 ll qPow(ll a,ll b)
     7 {
     8     ll ans=1;
     9     a %= MOD;
    10 
    11     while(b)
    12     {
    13         if(b&1)
    14             ans=ans*a%MOD;
    15 
    16         a=a*a%MOD;
    17         b >>= 1;
    18     }
    19     return ans;
    20 }
    21 ll Inv(ll a)///返回 a 的逆元
    22 {
    23     return qPow(a,MOD-2)%MOD;
    24 }
    25 int main()
    26 {
    27     int T;
    28     scanf("%d",&T);
    29     
    30     ll ans=1;
    31     while(T--)
    32     {
    33         int n,m;
    34         scanf("%d%d",&n,&m);
    35         ll cur;
    36         if(m == 0)
    37         {
    38             if(n != 1)
    39                 cur=0;
    40             else
    41                 cur=1;
    42         }
    43         else
    44             cur=Inv(n-1);///cur = {1/(n-1)}%MOD;
    45         
    46         ans=ans*cur%MOD;
    47         
    48         printf("%lld
    ",ans);
    49     }
    50     return 0;
    51 }
    View Code

    •想法

      打表找规律做出的题终究不是正解,只能解决当前题;


    F.Partition priblem(DFS)

    •题意

      有 2n 个人,任意两个人之间都存在竞争值;

      定义 v[ i ][ j ] 表示 i 与 j 的竞争值为 v[ i ][ j ];

      现让你将这 2n 个人划分成两组,每组有 n 人,组内的成员之间不存在竞争;

      求最大的竞争值;

      例如,假设 a 组有成员 1,2 , b 组有成员 3,4;

      其竞争值为 v[1][3] + v[1][4] + v[2][3] + v[2][4];

    •题解

      DFS+剪枝;

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int maxn=100;
     5 
     6 int n;
     7 ll sum;
     8 ll v[maxn][maxn];
     9 ///将这2n个人划分成a,b两组,每组有n人
    10 int a[maxn];
    11 int b[maxn];
    12 
    13 ///a组中的成员为a[1],a[2],...,a[cntA-1];
    14 ///b组中的成员为b[1],b[2],...,b[cntB-1];
    15 ///当前a,b两组的竞争值为cur
    16 ///在向a组或b组中增加新成员时,cur -= x;
    17 ///x指的是加入新成员后的组内竞争
    18 void DFS(int cntA,int cntB,ll cur,ll &ans)
    19 {
    20     if(ans >= cur)
    21         return ;
    22     if(cntA-1 > n || cntB-1 > n)
    23         return ;
    24     
    25     int k=cntA+cntB-1;
    26     if(k == 2*n+1)
    27     {
    28         ans=max(ans,cur);
    29         return ;
    30     }
    31     
    32     ll tmp=cur;
    33     a[cntA]=k;///k归到a组
    34     for(int i=1;i < cntA;++i)
    35         tmp -= v[a[i]][k];///x=∑v[a[i]][k]
    36     DFS(cntA+1,cntB,tmp,ans);
    37     
    38     tmp=cur;
    39     b[cntB]=k;///k归到b组
    40     for(int i=1;i < cntB;++i)
    41         tmp -= v[b[i]][k];///x=∑v[b[i]][k]
    42     DFS(cntA,cntB+1,tmp,ans);
    43 }
    44 ll Solve()
    45 {
    46     ll ans=0;
    47     DFS(1,1,sum,ans);
    48     
    49     return ans;
    50 }
    51 int main()
    52 {
    53     scanf("%d",&n);
    54     
    55     sum=0;
    56     for(int i=1;i <= n*2;++i)
    57         for(int j=1;j <= n*2;++j)
    58         {
    59             scanf("%lld",v[i]+j);
    60             if(j < i)
    61                 sum += v[i][j];
    62         }
    63     printf("%lld
    ",Solve());
    64     
    65     return 0;
    66 }
    View Code

    H.Second Large Rectangle(单调栈)

    •题意

           给你一个仅由 01 组成的 n×m 组成的矩阵;

           求仅由 1 组成的矩阵中,第二大的矩阵面积;

    •题解

          定义二维数组 h,h[ i ][ j ] 表示从(i,j) 位置开始向上连续的 1 的个数;

          例如:

       

      h[1][1] = 1 , h[2][1] = 0 , h[3][3] = 3 , h[4][1] = 1;

          对于第 i 行,首先求出 h[ i ][ j ] 后,然后通过单调栈算法求出以 h[ i ][ j ] 为高的最大的矩阵面积; 

      定义变量 f,s 分别记录第一大和第二大的矩阵的面积及相应的矩阵坐标;

          每到达一个新位置,判断是否需要更新 f,s ;

          最后,输出 s 矩阵所表示的面积;

    •Code

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=5e3+50;
      4  
      5 int n,m;
      6 char a[maxn][maxn];
      7 int h[maxn];
      8 int l[maxn];
      9 int r[maxn];
     10 stack<int >sta;
     11  
     12 struct Data
     13 {
     14     int a,b;
     15     int c,d;
     16     int val;
     17 }f,s;
     18  
     19 void Clear()
     20 {
     21     while(!sta.empty())
     22         sta.pop();
     23 }
     24 void Work()
     25 {
     26     Clear();
     27     for(int i=1;i <= m;++i)
     28     {
     29         while(!sta.empty() && h[sta.top()] >= h[i])
     30             sta.pop();
     31  
     32         l[i]=sta.empty() ? 1:sta.top()+1;
     33         sta.push(i);
     34     }
     35  
     36     Clear();
     37     for(int i=m;i >= 1;--i)
     38     {
     39         while(!sta.empty() && h[sta.top()] >= h[i])
     40             sta.pop();
     41  
     42         r[i]=sta.empty() ? m:sta.top()-1;
     43         sta.push(i);
     44     }
     45 }
     46 void updata(Data &tmp,int a,int b,int c,int d)
     47 {
     48     tmp.a=a;
     49     tmp.b=b;
     50     tmp.c=c;
     51     tmp.d=d;
     52  
     53     tmp.val=(c-a+1)*(d-b+1);
     54 }
     55 int Solve()
     56 {
     57     for(int i=0;i <= m;++i)
     58         h[i]=0;
     59  
     60     f=Data{0,0,0,0,0};
     61     s=Data{0,0,0,0,0};
     62  
     63     for(int i=1;i <= n;++i)
     64     {
     65         for(int j=1;j <= m;++j)
     66         {
     67             if(a[i][j] == '1')
     68                 h[j]++;
     69             else
     70                 h[j]=0;
     71         }
     72  
     73         Work();
     74  
     75         for(int j=1;j <= m;++j)
     76         {
     77             int cur=h[j]*(r[j]-l[j]+1);
     78  
     79             //(a,b) : cur 矩形左上角坐标
     80             //(c,d) : cur 矩形右下角坐标
     81             int a=i-h[j]+1;
     82             int b=l[j];
     83             int c=i;
     84             int d=r[j];
     85  
     86             if(cur >= f.val)
     87             {
     88                 if(!(a == f.a && b == f.b && c == f.c && d == f.d))
     89                     s=f;//如果当前面积 cur 所表示的矩形不等于 f 所表示的矩形
     90  
     91                 updata(f,a,b,c,d);
     92             }
     93             else if(cur >= s.val)
     94                 updata(s,a,b,c,d);
     95  
     96             //cur矩形在减少一行或一列后肯定不等于 f 所表示的矩形
     97             int cutX=(c-a)*(d-b+1);//减少一行后,判断是否更新 s
     98             int cutY=(c-a+1)*(d-b);//减少一列后,判断是否更新 s
     99  
    100             //判断是否更新 s
    101             if(cutX > s.val)
    102                 updata(s,a+1,b,c,d);
    103             if(cutY > s.val)
    104                 updata(s,a,b+1,c,d);
    105  
    106         }
    107     }
    108     return s.val;
    109 }
    110 int main()
    111 {
    112 //    freopen("C:\Users\hyacinthLJP\Desktop\in&&out\contest","r",stdin);
    113  
    114     scanf("%d%d",&n,&m);
    115     for(int i=1;i <= n;++i)
    116         scanf("%s",a[i]+1);
    117  
    118     printf("%d
    ",Solve());
    119  
    120     return 0;
    121 }
    View Code
  • 相关阅读:
    1.4.2.3. SETUP(Core Data 应用程序实践指南)
    1.4.2.2. PATHS(Core Data 应用程序实践指南)
    1.4.2.1. FILES(Core Data 应用程序实践指南)
    1.4.2. 实现 Core Data Helper 类(Core Data 应用程序实践指南)
    1.4.1. Core Data Helper 简介(Core Data 应用程序实践指南)
    1.4. 为现有的应用程序添加 Core Data 支持(Core Data 应用程序实践指南)
    1.3.2. App Icon 和 Launch Image(Core Data 应用程序实践指南)
    1.3.1. 新建Xcode项目并设置故事板(Core Data 应用程序实践指南)
    php验证邮箱是否合法
    如何使js函数异步执行
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/11219006.html
Copyright © 2011-2022 走看看