A - Mahmoud and Longest Uncommon Subsequence
两个序列最长即可。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int main()
{
char a[maxn],b[maxn];
scanf("%s",a);
getchar();
scanf("%s",b);
int la=strlen(a),lb=strlen(b);
if(strcmp(a,b)==0)
{
printf("-1\n");
}
else
{
printf("%d",max(la,lb));
}
return 0;
}
B - Mahmoud and a Triangle
定义为 :两边之和大于第三边。我的做法是排序一下,从大到小,要是后两个能相加大于第一个即可。
即 a[ i ]<a[ i +1 ]+a[ i+2 ],如果满足就可以找到要是不满足就找不到。
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int cmp(ll a,ll b)
{
return a>b;
}
int main()
{
int n;
scanf("%d",&n);
ll *a;
a=(ll *)calloc(n,sizeof(ll));
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
sort(a,a+n,cmp);
int flag=0;
for(int i=0;i<n&&!flag&i+2<n;i++)
{
if(a[i]<a[i+1]+a[i+2])
flag=1;
}
if(flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
return 0;
}
C - Mahmoud and a Message
这题我还真不会。。。没办法,只能百度找一下答案,还是要看半天的。
它的问题有点多。
题意:给定一个小写字母组成的字符串和每个小写字母最多存在长度为a[i]的子串中,输出满足条件的分割方案数,并输出所有方案中最长子串的长度和最少的分割次数。
思路:另dp[i]表示在第i个字符后面有一个横杠的方案数,从第i个往前枚举前一个横杠的位置j,设从i到合法的j的子串长度为l,则l=min(l,a[s[j]-'a']),若l<(i-j)则跳出循环。每次都dp[i]+=dp[j]。
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int a[30];
char str[1010];
int dp[1010];
int judge(int i,int j)
{
for(int k=i-j+1;k<=i;k++)
{
if(a[str[k]-'a']<j)
{
return 0;
}
}
return 1;
}
int main()
{
int n,i,j;
int minn[1010];
scanf("%d",&n);
scanf("%s",str+1);
for(int i=0;i<26;i++)
{
scanf("%d",&a[i]);
}
memset(dp,0,sizeof(dp));
dp[0]=1;
minn[0]=0;
int maxx=0;
for(int i=1;i<=n;i++)
{
minn[i]=inf;
for(j=1;j<=i;j++)
{
if(judge(i,j))
{
if(dp[i-j])
maxx=max(j,maxx);
dp[i]=(dp[i]+dp[i-j])%mod;
minn[i]=min(minn[i],minn[i-j]+1);
}
}
}
printf("%d\n%d\n%d\n",dp[n],maxx,minn[n]);
return 0;
}
D - Tic-tac-toe
Certainly, everyone is familiar with tic-tac-toe game. The rules are very simple indeed. Two players take turns marking the cells in a 3 × 3grid (one player always draws crosses, the other — noughts). The player who succeeds first in placing three of his marks in a horizontal, vertical or diagonal line wins, and the game is finished. The player who draws crosses goes first. If the grid is filled, but neither Xs, nor 0s form the required line, a draw is announced.
You are given a 3 × 3 grid, each grid cell is empty, or occupied by a cross or a nought. You have to find the player (first or second), whose turn is next, or print one of the verdicts below:
- illegal — if the given board layout can't appear during a valid game;
- the first player won — if in the given board layout the first player has just won;
- the second player won — if in the given board layout the second player has just won;
- draw — if the given board layout has just let to a draw.
The input consists of three lines, each of the lines contains characters ".", "X" or "0" (a period, a capital letter X, or a digit zero).
Print one of the six verdicts: first, second, illegal, the first player won, the second player won or draw.
X0X .0. .X.
second
这题我是补题时做出来了的,这个问题是什么呢?这个就是小时候我们玩的OX图,其中X是先手,O是后手。
它想问我们首先,这个OX图是否合法,
要是合法,它的有几种情况,
1、先手赢
2、后手赢
3、下一步应该是先手下
4、下一步应该是后手下、
5、平局。
其实难点不在于怎么判断 OX图里的情况。
而在于判断 不合法情况。
1、OX数目不合法,就比如,只要cnt X == cnt O+1 || O 都是数目不合法。
2、O赢了 不满足 cnt X ==cnt O。
3、X赢了 不满足 cnt X == cnt O +1。
4、双赢。
#include<stdio.h>
int owin,xwin,ocnt,xcnt;
bool check()
{
if(owin&&xwin)
{
return true;
}
else if(ocnt>xcnt||xcnt>ocnt+1)
{
return true;
}
else if(owin&&xcnt==ocnt+1)
{
return true;
}
else if(xwin&&ocnt==xcnt)
{
return true;
}
else
return false;
}
int main()
{
char G[4][4];
int row[3]={0},col[3]={0};
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%c",&G[i][j]);
if(G[i][j]=='X')
{
xcnt++;
row[j]++;
col[i]++;
}
else if(G[i][j]=='0')
{
ocnt++;
row[j]++;
col[i]--;
}
}
getchar();
}
if(G[0][0]==G[1][1]&&G[1][1]==G[2][2]&&G[0][0]=='X')
{
xwin=1;
}
if(G[0][0]==G[1][1]&&G[1][1]==G[2][2]&&G[0][0]=='0')
{
owin=1;
}
if(G[2][0]==G[1][1]&&G[1][1]==G[0][2]&&G[1][1]=='X')
{
xwin=1;
}
if(G[2][0]==G[1][1]&&G[1][1]==G[0][2]&&G[1][1]=='0')
{
owin=1;
}
if((G[0][0]==G[1][0]&&G[1][0]==G[2][0]&&G[2][0]=='X')
||(G[0][1]==G[1][1]&&G[1][1]==G[2][1]&&G[2][1]=='X')
||(G[0][2]==G[1][2]&&G[1][2]==G[2][2]&&G[2][2]=='X'))
{
xwin=1;
}
if((G[0][0]==G[1][0]&&G[1][0]==G[2][0]&&G[2][0]=='0')
||(G[0][1]==G[1][1]&&G[1][1]==G[2][1]&&G[2][1]=='0')
||(G[0][2]==G[1][2]&&G[1][2]==G[2][2]&&G[2][2]=='0'))
{
owin=1;
}
if((G[0][0]==G[0][1]&&G[0][1]==G[0][2]&&G[0][2]=='X')
||(G[1][0]==G[1][1]&&G[1][1]==G[1][2]&&G[1][2]=='X')
||(G[2][0]==G[2][1]&&G[2][1]==G[2][2]&&G[2][2]=='X'))
{
xwin=1;
}
if((G[0][0]==G[0][1]&&G[0][1]==G[0][2]&&G[0][2]=='0')
||(G[1][0]==G[1][1]&&G[1][1]==G[1][2]&&G[1][2]=='0')
||(G[2][0]==G[2][1]&&G[2][1]==G[2][2]&&G[2][2]=='0'))
{
owin=1;
}
if(check())
{
printf("illegal\n");
}
else if(xwin)
{
printf("the first player won\n");
}
else if(owin)
{
printf("the second player won\n");
}
else if(ocnt+xcnt==9)
{
printf("draw\n");
}
else if(xcnt==ocnt)
{
printf("first\n");
}
else if(ocnt+1==xcnt)
{
printf("second\n");
}
/* for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%c",G[i][j]);
}
printf("\n");
}
printf("%d %d %d %d \n",ocnt,xcnt,owin,xwin);*/
return 0;
}
E - 越狱
Description
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果
相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
Sample Output
HINT
6种状态为(000)(001)(011)(100)(110)(111)
这题不好想,我做过一次类似的题目,是牛客网上的一场新生题,叫开心的涂刷。
这个题其实是我们高中是学概率时学到的涂色问题。
怎么来分析这道题呢。
n个格子, m种颜色。
首先 我们算出全部情况, 它的情况为: n 的 m次方。
要是我们要它两两相邻不为同一种颜色呢,
1 、 2 、 3 、 4 、 5`````` n
m m-1 m-1 m-1 m-1 m-1
这不就是 m × ( n-1 )的(m-1)次方。
答案就是 找它的对立事件
ans = n 的 m次方 - m × ( n-1 )的(m-1)次方。
记得要快速幂,而且快速幂注意一点是 ( ans +mod )%mod。
#include<stdio.h>
typedef long long ll;
const ll mod=100003;
ll qpow(ll n,ll m)
{
ll ans=1;
n%=mod;
while(m)
{
if(m&1)
ans=(n*ans)%mod;
n=(n*n)%mod;
m/=2;
}
return ans;
}
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m );
printf("%lld\n",(qpow(n,m)-(qpow(n-1,m-1)*(n%mod)%mod)+mod)%mod);
return 0;
}
F - Crashing Robots
Description
A robot crashes with a wall if it attempts to move outside the area of the warehouse, and two robots crash with each other if they ever try to occupy the same spot.
Input
The second line contains two integers, 1 <= N, M <= 100, denoting the numbers of robots and instructions respectively.
Then follow N lines with two integers, 1 <= Xi <= A, 1 <= Yi <= B and one letter (N, S, E or W), giving the starting position and direction of each robot, in order from 1 through N. No two robots start at the same position.
![](https://i-blog.csdnimg.cn/blog_migrate/5c7adf6dcd1e44166dc55094bc35f881.jpeg)
Figure 1: The starting positions of the robots in the sample warehouse
Finally there are M lines, giving the instructions in sequential order.
An instruction has the following format:
< robot #> < action> < repeat>
Where is one of
- L: turn left 90 degrees,
- R: turn right 90 degrees, or
- F: move forward one meter,
and 1 <= < repeat> <= 100 is the number of times the robot should perform this single move.
Output
- Robot i crashes into the wall, if robot i crashes into a wall. (A robot crashes into a wall if Xi = 0, Xi = A + 1, Yi = 0 or Yi = B + 1.)
- Robot i crashes into robot j, if robots i and j crash, and i is the moving robot.
- OK, if no crashing occurs.
Only the first crash is to be reported.
Sample Input
4 5 4 2 2 1 1 E 5 4 W 1 F 7 2 F 7 5 4 2 4 1 1 E 5 4 W 1 F 3 2 F 1 1 L 1 1 F 3 5 4 2 2 1 1 E 5 4 W 1 L 96 1 F 2 5 4 2 3 1 1 E 5 4 W 1 F 4 1 L 1 1 F 20
Sample Output
Robot 1 crashes into the wall Robot 1 crashes into robot 2 OK Robot 1 crashes into robot 2
问题简单直白,还是简单阐述一下吧。
首先有 K 组示例。
地图为 A为行 , B 为列。
进入了每组示例时要输入。
输入 N 和 M。
N是有多少个机器人,M为多少个指令,
然后有N行。说明的是 N个机器人的位置和它具有的方向。
然后有M行,是需要的是 第 ?个机器人 实行(F, L,R)三个指令,执行多少次
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct robot
{
int x,y,dire;
}robot;
robot a[105];
int A,B,n,m;
bool check(int k)
{
if(a[k].x<=0||a[k].y<=0||a[k].x>A||a[k].y>B)
{
printf("Robot %d crashes into the wall\n",k);
return true;
}
for(int i=1;i<=n;i++)
{
if(i==k)
continue;
if(a[k].x==a[i].x&&a[k].y==a[i].y)
{
printf("Robot %d crashes into robot %d\n",k,i);
return true;
}
}
return false;
}
int dir[4][2]={
{1,0},
{0,-1},
{-1,0},
{0,1}
};
int main()
{
int T,i,j;
char ch;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&A,&B,&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d %d %c",&a[i].x,&a[i].y,&ch);
switch(ch)
{
case 'E':a[i].dire=0;break;
case 'S':a[i].dire=1;break;
case 'W':a[i].dire=2;break;
case 'N':a[i].dire=3;break;
}
}
bool flag=false;
int num,cnt;
for(i=0;i<m;i++)
{
scanf("%d %c %d",&num,&ch,&cnt);
switch(ch)
{
case 'L':a[num].dire=(a[num].dire-cnt%4+4)%4;break;
case 'R':a[num].dire=(a[num].dire+cnt%4)%4;break;
case 'F':
if(!flag)
{
for(j=0;j<cnt;j++)
{
a[num].x=a[num].x+dir[a[num].dire][0];
a[num].y=a[num].y+dir[a[num].dire][1];
flag=check(num);
if(flag)
break;
}
}
break;
}
}
if(!flag)
{
printf("OK\n");
}
}
return 0;
}