7月8号晚上8点和两位巨佬开了一场虚拟cf: [Helvetic Coding Contest 2018 online mirror (teams allowed, unrated)]

我这么蔡,只AC了A2、C1、C2、E1(被巨佬吊打)

我就说一下我写的几道题吧:

A2. Death Stars (medium)

The stardate is 1983, and Princess Heidi is getting better at detecting the Death Stars. This time, two Rebel spies have yet again given Heidi two maps with the possible locations of the Death Star. Since she got rid of all double agents last time, she knows that both maps are correct, and indeed show the map of the solar system that contains the Death Star. However, this time the Empire has hidden the Death Star very well, and Heidi needs to find a place that appears on both maps in order to detect the Death Star.

The first map is an N × M grid, each cell of which shows some type of cosmic object that is present in the corresponding quadrant of space. The second map is an M × N grid. Heidi needs to align those two maps in such a way that they overlap over some M × M section in which all cosmic objects are identical. Help Heidi by identifying where such an M × M section lies within both maps.

Input

The first line of the input contains two space-separated integers N and M (1 ≤ N ≤ 2000, 1 ≤ M ≤ 200, M ≤ N). The next N lines each contain M lower-case Latin characters (a-z), denoting the first map. Different characters correspond to different cosmic object types. The next M lines each contain N characters, describing the second map in the same format.

Output

The only line of the output should contain two space-separated integers i and j, denoting that the section of size M × M in the first map that starts at the i-th row is equal to the section of the second map that starts at the j-th column. Rows and columns are numbered starting from 1.

If there are several possible ways to align the maps, Heidi will be satisfied with any of those. It is guaranteed that a solution exists.

翻译后的人话:

给你两个矩阵,前一个\(N×M\),后一个\(M×N\),然后再两个矩阵中识别一个\(M×M\)的矩阵,这个矩阵都存在于两个矩阵中

好水啊,可以用kmp,不过我太蔡不会于是直接hash暴力匹配

这里用了单哈希,参考了巨佬队友tanao_的代码,我双哈希不知道为什么T飞(可能是我太蔡了)

直接上代码(把注释去掉就变成双hash了):

#include <cstdio>
#include <cctype>
#include <iostream>
#define reg register
#define int long long
using namespace std;
const int MaxN=2001;
const int MaxM=201;
const int inf=0x7ffffffffffffff; // 14 f
const int base1=131;
const int base2=13131;
const int p1=4503599627370001ll;
const int p2=4503599627391001ll;
int n,m;
string s1[MaxN],s2[MaxN];
int s1hash1[MaxN],s2hash1[MaxM][MaxN];
int s1hash2[MaxN],s2hash2[MaxM][MaxN];
template <class t> inline void rd(t &s)
{
s=0;
reg char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
return;
}
inline int gethash1(string s)
{
reg int res=0;
for(int i=0;i<s.length();++i)
res=(res*base1+s[i])%p1;
return res;
}
inline int gethash2(string s)
{
reg int res=0;
for(int i=0;i<s.length();++i)
res=(res*base2+s[i])%p2;
return res;
}
inline bool ck(int x,int y)
{
for(int i=1;i<=m;++i)
// if(s1hash1[x+i-1]!=s2hash1[i][y]||s1hash2[x+i-1]!=s2hash2[i][y])
if(s1hash1[x+i-1]!=s2hash1[i][y])
return false;
return true;
}
signed main(void)
{
rd(n);rd(m);
for(int i=1;i<=n;++i)
cin>>s1[i];
for(int i=1;i<=m;++i)
cin>>s2[i];
for(int i=1;i<=n;++i)
{
s1hash1[i]=gethash1(s1[i]);
// s1hash2[i]=gethash2(s1[i]);
}
for(int i=1;i<=m;++i)
for(int j=1;j<=n-m+1;++j)
{
s2hash1[i][j]=gethash1(s2[i].substr(j-1,m));
// s2hash2[i][j]=gethash2(s2[i].substr(j-1,m));
}
for(int i=1;i<=n-m+1;++i)
for(int j=1;j<=n-m+1;++j)
if(ck(i,j))
return printf("%lld %lld",i,j),0;
return 0;
}

C1. Encryption (easy)

Rebel spy Heidi has just obtained the plans for the Death Star from the Empire and, now on her way to safety, she is trying to break the encryption of the plans (of course they are encrypted – the Empire may be evil, but it is not stupid!). The encryption has several levels of security, and here is how the first one looks.

Heidi is presented with a screen that shows her a sequence of integers A and a positive integer p. She knows that the encryption code is a single number S, which is defined as follows:

Define the score of X to be the sum of the elements of X modulo p.

Heidi is given a sequence A that consists of N integers, and also given an integer p. She needs to split A into 2 parts such that:

  • Each part contains at least 1 element of A, and each part consists of contiguous elements of A.
  • The two parts do not overlap.
  • The total sum S of the scores of those two parts is maximized. This is the encryption code.

Output the sum S, which is the encryption code.

Input

The first line of the input contains two space-separated integer N and p (2 ≤ N ≤ 100 000, 2 ≤ p ≤ 10 000) – the number of elements in A, and the modulo for computing scores, respectively.

The second line contains N space-separated integers which are the elements of A. Each integer is from the interval [1, 1 000 000].

Output

Output the number S as described in the problem statement.

样例1

输入

4 10
3 4 7 2

输出

16

经过印度女工翻译后的人话:

把长度为n的序列分成两个部分,使每个子序列的和对p取模后的结果的和最大

样例解释1:

\((3+4) mod 10+(7+2) mod 10 = 16\)

\(n<=100000\) 直接前缀和暴力枚举断点水过

Code:

#include <cstdio>
#include <cctype>
#include <algorithm>
#define int long long
#define reg register
using namespace std;
const int MaxN=100001;
template <class t> inline void rd(t &s)
{
s=0;
reg char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
return;
}
int a[MaxN],f[MaxN];
inline int getsum(int l,int r)
{
return f[r]-f[l-1];
}
signed main(void)
{
int n,p;
reg int ans=0;
rd(n);rd(p);
for(int i=1;i<=n;++i)
rd(a[i]),f[i]=f[i-1]+a[i];
for(int i=1;i<n;++i)
ans=max(ans,(getsum(1,i)%p)+(getsum(i+1,n)%p));
printf("%lld",ans);
return 0;
}

C2. Encryption (medium)

Heidi has now broken the first level of encryption of the Death Star plans, and is staring at the screen presenting her with the description of the next code she has to enter. It looks surprisingly similar to the first one – seems like the Empire engineers were quite lazy...

Heidi is once again given a sequence A, but now she is also given two integers k and p. She needs to find out what the encryption key S is.

Let X be a sequence of integers, and p a positive integer. We define the score of X to be the sum of the elements of X modulo p.

Heidi is given a sequence A that consists of N integers, and also given integers k and p. Her goal is to split A into k part such that:

  • Each part contains at least 1 element of A, and each part consists of contiguous elements of A.
  • No two parts overlap.
  • The total sum S of the scores of those parts is maximized.

Output the sum S – the encryption code.

Input

The first line of the input contains three space-separated integer N, k and p (k ≤ N ≤ 20 000, 2 ≤ k ≤ 50, 2 ≤ p ≤ 100) – the number of elements in A, the number of parts A should be split into, and the modulo for computing scores, respectively.

The second line contains N space-separated integers that are the elements of A. Each integer is from the interval [1, 1 000 000].

Output

Output the number S as described in the problem statement.

上一题的升级版

人话:把长度为n的序列分成k个部分,使每个子序列的和对p取模后的结果的和最大

很明显,考虑dp

\(f[i][j]\) 表示前i个数分成j段时的最大结果

转移方程很简单,

\(f[i][j]=max(f[i][j],f[k][j-1]+(g[i]-g[k])mod p)\) \((0<=k<i)\)

解释一下,g[i]是前缀和,\(f[k][j-1]\)表示在第k个数断j-1个点时的最大结果,\((g[i]-g[k])\)就是k+1~i这段序列和,k是用来枚举用的,看不懂建议先去做一些基础的dp

分析一下复杂度\(O(n^2k)\),最大计算次数为\(2.0×10^{10}\),20亿,好,信心满满地相信CF的机子交上去

考虑优化,我们是不是可以把一个n搞成p来减少时间复杂度呢

\(f[i][j]\)表示前i个数对p取模后为i,分成j段时的最大结果

显而易见,首先,因为dp数组的第一维的范围只有\([0,p-1]\),那么\(f[i][j]\)只有可能从\(f[k][j-1]\)\((0<=k<p)\)转移过来,那么对应断点所得新的子序列的和就是\((g[i]-k)modp\),所以可以得到状态转移方程

\(f[i][j]=max(f[i][j],f[k][j-1]+(g[i]-k)modp)\)\(0<=k<p\)

于是,Code就出来了:

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#define reg register
#define int long long
using namespace std;
const int MaxN=20001;
const int MaxK=51;
template <class t> inline void rd(t &s)
{
s=0;
reg char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
return;
}
int n,k,p;
int a[MaxN],g[MaxN];
int f[MaxN][MaxK];
signed main(void)
{
memset(f,0x80,sizeof f);f[0][0]=0;
rd(n);rd(k);rd(p);
for(int i=1;i<=n;++i)
rd(a[i]),g[i]=g[i-1]+a[i],g[i]%=p;
for(int i=1;i<=n;++i)
for(int j=k;j;--j)
for(int k=0;k<p;++k)
f[g[i]][j]=max(f[g[i]][j],f[k][j-1]+(g[i]+p-k)%p);
printf("%lld",f[g[n]][k]);
return 0;
}

E1. Guard Duty (easy)

The Rebel fleet is afraid that the Empire might want to strike back again. Princess Heidi needs to know if it is possible to assign R Rebel spaceships to guard B bases so that every base has exactly one guardian and each spaceship has exactly one assigned base (in other words, the assignment is a perfect matching). Since she knows how reckless her pilots are, she wants to be sure that any two (straight) paths – from a base to its assigned spaceship – do not intersect in the galaxy plane (that is, in 2D), and so there is no risk of collision.

Input

The first line contains two space-separated integers R, B(1 ≤ R, B ≤ 10). For 1 ≤ i ≤ R, the i + 1-th line contains two space-separated integers xi and yi (|xi|, |yi| ≤ 10000) denoting the coordinates of the i-th Rebel spaceship. The following B lines have the same format, denoting the position of bases. It is guaranteed that no two points coincide and that no three points are on the same line.

Output

If it is possible to connect Rebel spaceships and bases so as satisfy the constraint, output Yes, otherwise output No (without quote).

使用谷歌翻译然后看看样例再大胆的猜想一下就看懂题意了,其实我当时也不知道我能一次A

还好我当时猜对了题意

有R个叛军基地和B个守卫基地,要求一种匹配,使每一个叛军基地都和一个守卫基地连线,如果存在一种连线方法能让每一个基地都有匹配并且这些线段两两不相交,那么输出Yes,否则输出No

\(1<=R,B<=10\),直接暴力枚举每一种情况,判断;如果\(R!=B\),直接输出No

暴力好写,但是怎么判断两条线段是否相交呢?

这里使用了快速排斥实验跨立实验法,参考一位巨佬的博客(好几个月前看过,好不容易翻出来的)

快速排斥实验:判断两条线段在 x 以及 y 坐标的投影是否有重合

人话:若A线段中x较大的端点比B线段中x较小的端点的x要小,

​ 或A线段中y较大的端点比B线段中y较小的端点的y要小,则AB线段不相交

如图,图(1)和图(2)可以自己推出符合快速排斥,可图(3)就不符合快速排斥了

那么就要用到跨立实验法,也就是矢量叉积:

设矢量 \(P = (x1, y1),Q = ( x2, y2 )\),则矢量叉积定义为:\(P×Q = x1×y2 - x2×y1\)

有$P×Q = - ( Q×P ) $和 \(P×( - Q ) = - ( P×Q )\)

若 \(P×Q > 0\) , 则 \(P\) 在 \(Q\) 的顺时针方向。

若 \(P×Q < 0\) , 则 \(P\) 在 \(Q\) 的逆时针方向。

若 \(P×Q = 0\) , 则 \(P\) 与 \(Q\) 共线,但可能同向也可能反向。

(1):

如果两线段相交那么就意味着它们互相跨立,即如上图点 A 和 B 分别在线段 CD 两侧,点 C 和 D 分别在线 AB 两侧。

判断 A 点与 B 点是否在线段 DC 的两侧,即向量 A-D 与向量 B-D 分别在向量 C-D 的两端,也就是其叉积是异号的,即 。

同时也要证明 C 点与 D 点在线段 AB 的两端,两个同时满足,则表示线段相交。

(2):临界情况,也就是上式恰好等于 0 的情况下:

当出现如上图所示的情况的时候,显然,这种情况是相交的。只要将等号直接补上即可。

(3)再看看上面我给的图(3):

当出现如上所示的情况的时候,叉积都为 0, 可以通过跨立实验,但是两个线段并没有交点。不过还好,这种情况在第一步快速排斥已经被排除了。

给出AC代码:

#include <cstdio>
#include <cctype>
#include <iostream>
#include <cstdlib>
#define reg register
using namespace std;
const int MaxN=11;
struct Node
{
int x,y;
}a[MaxN],b[MaxN];
struct Line
{
int xa,xb,ya,yb;
}E[10001];
int en;
template <class t> inline void rd(t &s)
{
s=0;
reg char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
return;
}
inline bool tix(Line x,Line y)
{
if ((x.xa > x.xb ? x.xa : x.xb) < (y.xa < y.xb ? y.xa : y.xb) ||
(x.ya > x.yb ? x.ya : x.yb) < (y.ya < y.yb ? y.ya : y.yb) ||
(y.xa > y.xb ? y.xa : y.xb) < (x.xa < x.xb ? x.xa : x.xb) ||
(y.ya > y.yb ? y.ya : y.yb) < (x.ya < x.yb ? x.ya : x.yb))
return false;
if ((((x.xa - y.xa)*(y.yb - y.ya) - (x.ya - y.ya)*(y.xb - y.xa))*
((x.xb - y.xa)*(y.yb - y.ya) - (x.yb - y.ya)*(y.xb - y.xa))) > 0 ||
(((y.xa - x.xa)*(x.yb - x.ya) - (y.ya - x.ya)*(x.xb - x.xa))*
((y.xb - x.xa)*(x.yb - x.ya) - (y.yb - x.ya)*(x.xb - x.xa))) > 0)
return false;
return true;
}
int R,B;
bool vis[MaxN];
inline bool ck()
{
for(int i=1;i<=R;++i)
for(int j=i+1;j<=B;++j)
if(tix(E[i],E[j]))
return false;
return true;
}
inline void dfs(int dep)
{
if(dep>R)
{
if(ck())
{
puts("Yes");
exit(0);
}
return;
}
for(int i=1;i<=B;++i)
if(!vis[i])
{
vis[i]=true;
E[dep].xa=a[dep].x;
E[dep].ya=a[dep].y;
E[dep].xb=b[i].x;
E[dep].yb=b[i].y;
dfs(dep+1);
vis[i]=false;
}
return;
}
signed main(void)
{
rd(R);rd(B);
if(R!=B)
return puts("No"),0;
for(int i=1;i<=R;++i)
{
rd(a[i].x);rd(a[i].y);
}
for(int i=1;i<=B;++i)
{
rd(b[i].x);rd(b[i].y);
}
dfs(1);
puts("No");
return 0;
}

第一次写cf的解题报告awa

20190708三人开黑CF模拟赛的更多相关文章

  1. 20190728三人开黑517codingACM模拟赛

    三人组队开黑ACM膜你赛 果然我最蔡 我就写了ACF所以就写这些吧awa Problem A 人话:给你一个w×h的矩形蛋糕,然后告诉你两个蜡烛的坐标,两个蜡烛都在网格点上且不在蛋糕边缘,问如何切一刀 ...

  2. 20190710双人开黑CF模拟赛

    Codeforces Round #571 (Div. 2) 日常被tanao_大佬带飞,我AC了A和C(B题没了...否则tanao_大佬肯定把我吊打) A. Vus the Cossack and ...

  3. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  4. 两个乒乓球队进行比赛,各出三人。 甲队为a,b,c三人,乙队为x,y,z三人。 已抽签决定比赛名单。 有人向队员打听比赛的名单。 a说他不和x比,c说他不和x,z比, 请编程序找出三队赛手的名单。

    题目:两个乒乓球队进行比赛,各出三人. 甲队为a,b,c三人,乙队为x,y,z三人. 已抽签决定比赛名单. 有人向队员打听比赛的名单. a说他不和x比,c说他不和x,z比, 请编程序找出三队赛手的名单 ...

  5. 计蒜客T2202 数三角形(提高组2017模拟赛(三)day2T3) LZOJ3878攻略

    今天模拟赛考了一道计蒜客NOIP2017模拟赛(三)day2T3的数三角形,原题链接 https://nanti.jisuanke.com/t/T2202 ,LZOJ3878攻略.场上想了很久都没转化 ...

  6. 代码实现:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。 已抽签决定比赛名单。有人向队员打听比赛的名单。 a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单

    /*两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人. 已抽签决定比赛名单.有人向队员打听比赛的名单. a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单.*/ ...

  7. python基础练习题(题目 两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单)

    day14 --------------------------------------------------------------- 实例022:比赛对手 题目 两个乒乓球队进行比赛,各出三人. ...

  8. NOIp2018模拟赛三十六

    好久没打模拟赛了...今天一样是两道国集,一道bzoj题 成绩:13+0+95=108 A题开始看错题了...导致样例都没看懂,结果xfz提醒我后我理解了一个我自认为正确的题意(事实证明我和xfz都错 ...

  9. 冲刺$\mathfrak{CSP-S}$集训模拟赛总结

    开坑.手懒并不想继续一场考试一篇文. 既没必要也没时间侧边栏的最新随笔题解反思相间也丑 而且最近越来越懒了竟然都不写题解了……开坑也是为了督促自己写题解. 并不想长篇大论.简要题解也得写啊QAQ. 目 ...

随机推荐

  1. 通过脚本实现对web的健康检查

    前面的文章中(https://www.cnblogs.com/zyxnhr/p/10707932.html),通过nginx的第三方模块实现对web端的一个监控,现在通过一个脚本实现对第三方的监控 脚 ...

  2. 小米6X谷歌套件

    话不多说真机测试完美适配,安卓万物基于谷歌链接如下(个别MIUI版本不同谷歌商店会报错,如遇到请留言我会第一时间回复解决) 链接:https://pan.baidu.com/s/1b2Cs0u9J2b ...

  3. matlab读取excel文件中的数据

    1.读取sheet1中的所有数据 1.1首先我们建立一个sheet表,表名为‘111’ 1.2 默认这些文本以及数字都放在sheet1中,我们将此excel选入当前工作目录(必要步骤), 选入当前工作 ...

  4. 从 posix_spawn() 函数窥探漏洞逃逸

    posix_spawn() 函数是用来在Linux上创建子进程的,头文件是 #include <spawn.h> ,语法如下: #include <spawn.h> int p ...

  5. creator 2.0版本对于preloadScene函数获取加载进度

    有时候,当我们场景上挂载的资源过多时,我们使用cc.director.loadScene切换场景时会等一段时间才会切换过去,这对游戏的体验是相当不好的.所以我们可以使用cc.director.prel ...

  6. Java 多线程安全问题简单切入详细解析

    线程安全 假如Java程序中有多个线程在同时运行,而这些线程可能会同时运行一部分的代码.如果说该Java程序每次运行的结果和单线程的运行结果是一样的,并且其他的变量值也都是和预期的结果是一样的,那么就 ...

  7. 树上对抗搜索 - 树形dp

    Alice and Bob are going on a trip. Alice is a lazy girl who wants to minimize the total travelling d ...

  8. Tarjin + 缩点

    链接:https://www.nowcoder.com/acm/contest/81/C来源:牛客网 题目描述 给出一个 0 ≤ N ≤ 105 点数.0 ≤ M ≤ 105 边数的有向图, 输出一个 ...

  9. python认识及环境变量

    什么是python? python是一种脚本语言,是高级语言.计算机只能识别机器语言,在机器语言上是汇编语言,再往上是高级语言.高级语言的基础是C语言. python语言较为简单,易入门. pytho ...

  10. [题解][Codeforces]Good Bye 2019 简要题解

    构造题好评,虽然这把崩了 原题解 A 题意 二人游戏,一个人有 \(k_1\) 张牌,另一个人 \(k_2\) 张,满足 \(2\le k_1+k_2=n\le 100\),每张牌上有一个数,保证所有 ...