阿里的新游戏
阿里九游开放平台近日上架了一款新的益智类游戏——成三棋。成三棋是我国非常古老的一个双人棋类游戏,其棋盘如下图所示:
成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋子。我们可以用坐标系来描述棋盘:
如果一条线段上的三个交叉点都被同一玩家的棋子占据的话,则称这条线段被该玩家 成三。现在,小红和小明两人在游戏平台上下棋,其中小红的棋子是黑色的。请你帮小红计算他成三的线段数。
样例对应的棋盘如下:
输入格式
输入第一行两个整数 n,m(3≤n,m≤9)n,m(3 \le n, m \le 9)n,m(3≤n,m≤9),nnn 表示小红的棋子数,mmm 表示小明的棋子数。
接下来 nnn 行输入小红的棋子坐标。
接下来 mmm 行输入小明的棋子坐标。
输入保证坐标合法,并且棋子之间不重合。
输出格式
输出小红成三的线段数。
样例输入
6 3
-1 0
-2 0
-3 0
-1 -1
-1 1
1 0
0 2
0 3
2 2
样例输出
2
模拟,水题,考虑下每行每列即可。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100],b[100],c[10];
int main()
{
int n,m,x,y;
cin >> n >> m;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(int i = 0;i < n; ++i)
{
cin>>x>>y;
x+=3,y+=3;
if(x!=3) ++a[x];
else
{
if(y > 3) ++c[0];
else ++c[1];
}
if(y!=3) ++b[y];
else
{
if(x < 3) ++c[2];
else ++c[3];
}
}
for(int i = 0;i < m; ++i) cin>>x>>y;
int ans = 0;
for(int i = 0;i <= 6; ++i)
{
if(i < 4)
{
if(c[i] == 3) ++ans;
}
if(i == 3) continue;
if(a[i] == 3) ++ans;
if(b[i] == 3) ++ans;
}
cout<<ans<<endl;
return 0;
}
阿里天池的新任务(简单)
阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 ttt,判断它在另一个根据规则生成的 DNA 碱基序列 sss 中出现了多少次。
首先,定义一个序列 www:
wi={b,i=0(wi−1+a)modn,i>0\displaystyle w_{i} = \begin{cases}b, & i = 0\\(w_{i-1} + a) \mod n, & i > 0\end{cases}wi={b,(wi−1+a)modn,i=0i>0
接下来,定义长度为 nnn 的 DNA 碱基序列 sss(下标从 000 开始):
si={A,(L≤wi≤R)∧(wi mod 2=0)T,(L≤wi≤R)∧(wi mod 2=1)G,((wi<L)∨(wi>R))∧(wi mod 2=0)C,((wi<L)∨(wi>R))∧(wi mod 2=1)\displaystyle s_{i} = \begin{cases}A , & (L \le w_{i} \le R) \land (w_{i}\ \mathrm{mod}\ 2 = 0)\\T , & (L \le w_{i} \le R) \land (w_{i}\ \mathrm{mod}\ 2 = 1)\\G , & ((w_{i} < L) \lor (w_{i} > R)) \land (w_{i}\ \mathrm{mod}\ 2 = 0)\\C , & ((w_{i} < L) \lor (w_{i} > R)) \land (w_{i}\ \mathrm{mod}\ 2 = 1)\end{cases} si=⎩⎪⎪⎪⎨⎪⎪⎪⎧A,T,G,C,(L≤wi≤R)∧(wi mod 2=0)(L≤wi≤R)∧(wi mod 2=1)((wi<L)∨(wi>R))∧(wi mod 2=0)((wi<L)∨(wi>R))∧(wi mod 2=1)
其中 ∧\land∧ 表示“且”关系,∨\lor∨ 表示“或”关系,a mod ba\ \mathrm{mod}\ ba mod b 表示 aaa 除以 bbb 的余数。
现给定另一个 DNA 碱基序列 ttt,以及生成 sss 的参数 n,a,b,L,Rn , a , b , L , Rn,a,b,L,R,求 ttt 在 sss 中出现了多少次。
输入格式
数据第一行为 555 个整数,分别代表 n,a,b,L,Rn , a , b , L , Rn,a,b,L,R。第二行为一个仅包含A
、T
、G
、C
的一个序列 ttt。
数据保证 0<a<n,0 < a < n,0<a<n, 0≤b<n,0 \le b < n,0≤b<n, 0≤L≤R<n,0 \le L \le R < n,0≤L≤R<n, ∣t∣≤106|t| \le 10^{6}∣t∣≤106,a,na,na,n 互质。
对于简单版本,1≤n≤1061 \leq n \leq 10^{6}1≤n≤106;
输出格式
输出一个整数,为 ttt 在 sss 中出现的次数。
样例说明
对于第一组样例,生成的 sss 为TTTCGGAAAGGCC
。
样例输入1
13 2 5 4 9
AGG
样例输出1
1
样例输入2
103 51 0 40 60
ACTG
样例输出2
5
裸的KMP,然而并不知道当时为什么写崩了。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char z[1000010],m[1000010];
int Next[1000010];
void Getnext()
{
int i = 0,j = -1;
Next[i] = -1;
while(m[i] != '\0')
{
while(j != -1 && m[i] != m[j]) j = Next[j];
if(m[++i] != m[++j]) Next[i] = j;
else Next[i] = Next[j];
}
}
int KMP()
{
int i = 0,j = 0,ans = 0;
while(z[i] != '\0')
{
while(j != -1 && z[i] != m[j]) j = Next[j];
++i,++j;
if(j != -1 && m[j] == '\0') ++ans;
}
return ans;
}
int main()
{
int n,a,b,l,r,t;
scanf("%d %d %d %d %d",&n,&a,&b,&l,&r);
scanf(" %s",m);
t = b;
for(int i = 0;i < n; ++i)
{
if(t >= l && t <= r)
{
if(t % 2 == 1) z[i] = 'T';
else z[i] = 'A';
}
else
{
if(t % 2 == 1) z[i] = 'C';
else z[i] = 'G';
}
t = (t + a) % n;
}
Getnext();
printf("%d\n",KMP());
return 0;
}