【LDU】2018个人PK赛#2

A - Mahmoud and Longest Uncommon Subsequence 

CodeForces - 766A 

While Mahmoud and Ehab were practicing for IOI, they found a problem which name was Longest common subsequence. They solved it, and then Ehab challenged Mahmoud with another problem.

Given two strings a and b, find the length of their longest uncommon subsequence, which is the longest string that is a subsequence of one of them and not a subsequence of the other.

A subsequence of some string is a sequence of characters that appears in the same order in the string, The appearances don't have to be consecutive, for example, strings "ac", "bc", "abc" and "a" are subsequences of string "abc" while strings "abbc" and "acb" are not. The empty string is a subsequence of any string. Any string is a subsequence of itself.

Input

The first line contains string a, and the second line — string b. Both of these strings are non-empty and consist of lowercase letters of English alphabet. The length of each string is not bigger than 105 characters.

Output

If there's no uncommon subsequence, print "-1". Otherwise print the length of the longest uncommon subsequence of a and b.

Examples
input
abcd
defgh
output
5
input
a
a
output
-1
Note

In the first example: you can choose "defgh" from string b as it is the longest subsequence of string b that doesn't appear as a subsequence of string a.


题目大意是,解决了最长公共子序列,想找一下,最长不公共子序列,如果没找到那就输出  ‘ -1 ’,要是找到就输出

两个序列最长即可。


#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 

CodeForces - 766B 

Mahmoud has n line segments, the i-th of them has length ai. Ehab challenged him to use exactly 3 line segments to form a non-degenerate triangle. Mahmoud doesn't accept challenges unless he is sure he can win, so he asked you to tell him if he should accept the challenge. Given the lengths of the line segments, check if he can choose exactly 3 of them to form a non-degenerate triangle.

Mahmoud should use exactly 3 line segments, he can't concatenate two line segments or change any length. A non-degenerate triangle is a triangle with positive area.

Input

The first line contains single integer n (3 ≤ n ≤ 105) — the number of line segments Mahmoud has.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the lengths of line segments Mahmoud has.

Output

In the only line print "YES" if he can choose exactly three line segments and form a non-degenerate triangle with them, and "NO" otherwise.

Examples
input
5
1 5 3 2 4
output
YES
input
3
4 1 2
output
NO
Note

For the first example, he can use line segments with lengths 24 and 5 to form a non-degenerate triangle.


题意是:能不能在一堆数字中找出能构成三角形的,这个三角形不能是  a+ b==c,这个就是我们三角形的定义。
定义为 :两边之和大于第三边。我的做法是排序一下,从大到小,要是后两个能相加大于第一个即可。

即   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 

CodeForces - 766C 

这题我还真不会。。。没办法,只能百度找一下答案,还是要看半天的。

它的问题有点多。

题意:给定一个小写字母组成的字符串和每个小写字母最多存在长度为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 

CodeForces - 3C

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.
Input

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).

Output

Print one of the six verdicts: firstsecondillegalthe first player wonthe second player won or draw.

Examples
input
X0X
.0.
.X.
output
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 - 越狱 

HYSBZ - 1008 

Description

  监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果
相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱

Input

  输入两个整数M,N.1<=M<=10^8,1<=N<=10^12

Output

  可能越狱的状态数,模100003取余

Sample Input

2 3

Sample Output

6

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 

POJ - 2632

Description

In a modernized warehouse, robots are used to fetch the goods. Careful planning is needed to ensure that the robots reach their destinations without crashing into each other. Of course, all warehouses are rectangular, and all robots occupy a circular floor space with a diameter of 1 meter. Assume there are N robots, numbered from 1 through N. You will get to know the position and orientation of each robot, and all the instructions, which are carefully (and mindlessly) followed by the robots. Instructions are processed in the order they come. No two robots move simultaneously; a robot always completes its move before the next one starts moving. 
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 first line of input is K, the number of test cases. Each test case starts with one line consisting of two integers, 1 <= A, B <= 100, giving the size of the warehouse in meters. A is the length in the EW-direction, and B in the NS-direction. 
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. 
 
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

Output one line for each test case: 
  • 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值