Gym 101845(2018 ACM-ICPC, Universidad Nacional de Colombia Programming Contest)

Problem A


Problem B

分析:

暴力查找,由操作 1 1 1,我们可以知道原串的第一位可以匹配结果串的每一位,所以 O ( n ) \mathcal{O}(n) O(n)枚举对齐判断就好;由操作 2 2 2,对于每一个对齐好的原串,我们要花最少次数变成答案串,我们可以确定一个位置,然后进行变换,这里有三种情况:

  1. 变选定位置和它的后一个位置
  2. 变选定位置和它的前一个位置
  3. 变选定位置和它的后一个位置,再变选定位置和它的前一个位置,即选定位置变了两次
    接着根据递推关系把原串变了,在最后一次变换后判断可不可行,不同对齐的情况取 min \text{min} min就好。

整体时间复杂度 O ( n 2 ) \mathcal{O}(n^2) O(n2)

代码:

Code


Problem C

题意:

给你两个串 s t r 1 str1 str1 s t r 2 str2 str2以及 m m m种操作,对于第 i i i操作你可以花费 c o s t i cost_i costi元,将字符 c i c_i ci编程字符 v i v_i vi。现在问你将 s t r 1 str1 str1转化为 s t r 2 str2 str2的最小花费。

分析:

考虑将这 m m m种操作的关系连边,并形成一个关系图。要想使得 s t r 1 str1 str1转化成 s t r 2 str2 str2的花费最少,显然是对于 s t r 1 str1 str1中的每一个跟 s t r 2 str2 str2不同的字符,我们要在关系图中找最小的花费。

因此这显然是一个多元最短路的问题,我们用 Floyd \text{Floyd} Floyd即可。

代码:

Code


Problem D

题意:

给你一个有 n n n个顶点的多边形,现在有 m m m个点对 ( x , y ) (x,y) (x,y),现在让你求出这 m m m个点对中, x x x y y y所夹的最大的突变型的面积。

分析:

首先,对于一个 n n n边形,如果要求出他的面积,则我们可以把他划分成 n − 1 n-1 n1个三角形,之后我们只需要用叉积的形式求出这 n − 1 n-1 n1个三角形的面积即可。

而现在这个题目中,需要我们求 m m m个由点对 ( x , y ) (x,y) (x,y)围城的多边形,如果我们用上面的做法去做时间复杂度显然会达到 O ( n m ) \mathcal{O}(nm) O(nm)

但是我们发现,在我们求一个 n n n边形的面积的时候,我们是采用将面积累加的形式,而由此,我们可以采用前缀和去优化。

我们设 sum[i] \text{sum[i]} sum[i]为前 i i i个点所围成的多边形的面积,我们画一下图之后可以发现,点对 ( x , y ) (x,y) (x,y)所围成的面积即为: sum[y-1]-sum[x]-(p[x]    ˆ  p[y])  \text{sum[y-1]-sum[x]-(p[x] \^ ~p[y]) } sum[y-1]-sum[x]-(p[x]  ˆ p[y]) 

代码:

Code


Problem E

题意:

给你一个边长为 n n n的正三角形,正三角形的每条边都有 n − 1 n-1 n1条线跟对应的边平行,且这 n − 1 n-1 n1条线都是平分线。

现在问你,在这样的一个三角形中,有多少个点对 ( x , y ) (x,y) (x,y),使得由他们组成的线段 x y xy xy中,包含着点 c c c,使得点 c c c也是这个三角形的顶点。

分析:

因为 n n n比较小,因此我们可以打表。显然我们可以把这个边长为 n n n ( 1 + n ) ∗ n 2 \frac{(1+n)*n}{2} 2(1+n)n个顶点的坐标都表示出来,其次我们可以首先枚举线段的两个顶点 x , y x,y x,y,再枚举第三个点 z z z,判断是否存在一个点 z z z在线段 x , y x,y x,y中。

之后打表获取答案即可,打表的时间复杂度为 O ( n 5 ) \mathcal{O}(n^5) O(n5),鉴于 n n n还是比较小,还是可以在比较快的时间内得出答案的。

而这题也有时间复杂度为 O ( n 2 ) \mathcal{O}(n^2) O(n2)的优秀算法,有时间再更新。


Problem F

题意:

n n n支队伍,每个队伍有 3 3 3个队员,每个队伍都有一个或多个擅长的领域(分别为A到Z)。而一个队伍最擅长的领域取决于他们中出现次数最多的(如果有多个则都是)。

现在规定,每个领域最多只能有 k k k个队伍擅长,现在问你,最多有多少个队伍符合条件。

分析:

网络流的裸题。

我们考虑先让每个队伍跟他符合条件的领域连边。

因为每个领域最多只能有 k k k个队伍擅长,因此,我们只需要对每个领域向超级汇点连接一条大小为 k k k的边限流即可。

最后把超级源点都给每个队伍连一条大小为 1 1 1的边作为流量,最后对这张图跑最大流即可。

代码:

Code


Problem G

分析:

先把每个字母的取和不取的概率算出来,要用到乘法逆元;接着进行 d p dp dp d p [ i ] [ j ] dp[i][j] dp[i][j]表示到长度i时猜中到第 j j j个的概率,最后将所有猜中到第 m m m个的概率加起来就是答案。
复杂度 O ( n ∗ m ) \mathcal{O}(n*m) O(nm)

代码:

Code


Problem H

温暖的签到题,只需要知道平年每过一年星期数+1,如果是闰年,过一年后星期数+2即可。

Code


Problem I

貌似是一个温暖的签到题,可能因为没有外榜大家都没有很快的 A C AC AC

实质上只需要模拟一下二进制循环移位的过程就结束了。

Code


Problem J

题意:

n n n个点, m m m条边。对于第 i i i条边,你可以从 u i u_i ui走到 v i v_i vi,花费 c i c_i ci元,花费 t i t_i ti时间。同时,你只能在时间 s i s_i si时候进行移动,且你只能在每 s i + f i 、 s i + 2 ∗ f i … s i + n ∗ f i s_i+f_i 、s_i+2*f_i \dots s_i+n*f_i si+fisi+2fisi+nfi时刻进行移动。现在问你从 1 1 1号结点走到 n n n号结点的最少时间以及在此基础下的最小的花费。

分析:

虽然多了一个移动时间的限制,但是本质上还是一个最短路径的问题。

我们发现等待的过程可以分为两种:

  1. 当前的时间 c u r ≤ s i cur\leq s_i cursi
  2. 当前的时间 c u r > s i cur > s_i cur>si

对于第一种情况,我们显然只能等待到 s i s_i si时候后,再花费 t i t_i ti的时间,故对于情况 1 1 1,此时需要花费的累计的时间为 c u r = s i + t i cur=s_i+t_i cur=si+ti

而对于第二种情况,要使的花费时间最小,我们必然想要等到一个最近的发车点,因此我们只需要获取需要等待的时间间隔 c u r − s i f i + 1 \frac{cur-s_i}{f_i}+1 ficursi+1,并用这个间隔算出最终所需的时间。

而倘若解决了上诉时间问题,之后我们只需要利用所算出的时间进行松弛操作即可。

代码:

Code


Problem K


Problem L

分析:

构造题,对于一个边长为 N = 2 n N=2^n N=2n的矩阵,我们可以每次对它一分为 4 4 4,类似“田”字,然后查找哪个子矩阵有一个点被占用,即有被填过或为一开始的 ( x , y ) (x,y) (x,y),然后在四个矩阵的交界处,填上一个 L L L,这个 L L L经过另外三个矩阵,这时候四个子矩阵都有一个点被占用了,接下来我们对子矩阵再进行同样的操作,直到矩阵不可再分。

最后填色,对你填 L L L过程中的 L L L打标记,最后 % 26 \%26 %26填字母就行,要说正确性,题目中 2 n 2^n 2n的矩阵, n n n最大才 11 11 11,你递归过程中,按顺序来,碰撞概率是极低的吧
复杂度 O ( N ∗ N ) \mathcal{O}(N*N) O(NN)

代码:

Code


Problem M

分析:

一个比较简单的概率的问题……

代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,k;
int main(){
    cin>>a>>b>>k;
    double ans=0;
    ll res=b-k+1;
    if (k>b) ans=1.0*b/k;
    else  ans=1.0*((k-1)+1.0*res/(res+a))/k;
    printf("%.7f\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值