学习总结14

# 【CSGRound1】天下第一

## 题目背景

天下第一的 cbw 以主席的身份在 8102 年统治全宇宙后,开始了自己休闲的生活,并邀请自己的好友每天都来和他做游戏。由于 cbw 想要显出自己平易近人,所以 zhouwc 虽然是一个蒟蒻,也有能和 cbw 玩游戏的机会。

## 题目描述

游戏是这样的:

给定两个数 x,y,与一个模数 p。

cbw 拥有数 x,zhouwc 拥有数 y。

第一个回合:x<-(x+y)mod p。

第二个回合:y<-(x+y)mod p。

第三个回合:x<-(x+y)mod p。

第四个回合:y<-(x+y)mod p。

以此类推....

如果 x 先到 0,则 cbw 胜利。如果 y 先到 0,则 zhouwc 胜利。如果 x,y 都不能到 0,则为平局。

cbw 为了捍卫自己主席的尊严,想要提前知道游戏的结果,并且可以趁机动点手脚,所以他希望你来告诉他结果。

## 输入格式

有多组数据。

第一行:T 和 p 表示一共有 T 组数据且模数都为 p。

以下 T 行,每行两个数 x,y。

## 输出格式

共 T 行

1 表示 cbw 获胜,2 表示 zhouwc 获胜,```error``` 表示平局。

## 样例 #1

### 样例输入 #1

```
1 10
1 3
```

### 样例输出 #1

```
error
```

## 样例 #2

### 样例输入 #2

```
1 10
4 5
```

### 样例输出 #2

```
1
```

## 提示

1 <= T <= 200。

1 <= x,y,p <= 10000。

解题思路

运用记忆化搜索,用一个数组来保存对应的x,y的结果。

代码

#include 
#include 
using namespace std;
short g[10001][10001];
int p;
int dfs(int x,int y)
{
    int x1,y1;
    if(g[x][y]==1)
        return -1;
    g[x][y]=1;
    x1=(x+y)%p;                                 //保存第一回合的值
    y1=(x1+y)%p;                                //第二回合的值
    if(x1==0)
        return g[x1][y]=1;
    if(y1==0)
        return g[x1][y1]=2;
    return g[x1][y1]=dfs(x1,y1);
}
int main()
{
    int x,y,z,t,k;
    scanf("%d%d",&t,&p);
    for(z=0;z

# 【模板】KMP

## 题目描述

给出两个字符串 s1 和 s2,若 s1 的区间 [l, r] 子串与 s2 完全相同,则称 s2 在 s1 中出现了,其出现位置为 l。  
现在请你求出 s2 在 s1 中所有出现的位置。

定义一个字符串 s 的 border 为 s 的一个非 s 本身的子串 t,满足 t 既是 s 的前缀,又是 s 的后缀。  
对于 s2,你还需要求出对于其每个前缀 s' 的最长 border t' 的长度。

## 输入格式

第一行为一个字符串,即为 s1。  
第二行为一个字符串,即为 s2。

## 输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 s2 在 s1 中出现的位置。  
最后一行输出 |s2| 个整数,第 i 个整数表示 s2 的长度为 i 的前缀的最长 border 长度。

## 样例 #1

### 样例输入 #1

```
ABABABC
ABA
```

### 样例输出 #1

```
1
3
0 0 1
```

## 提示

### 样例 1 解释
 
对于 s2 长度为 3 的前缀 `ABA`,字符串 `A` 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 1。


### 数据规模与约定

**本题采用多测试点捆绑测试,共有 3 个子任务**。

- Subtask 1(30 points):|s1| <= 15,|s2| <= 5。
- Subtask 2(40 points):|s1| <= 10^4,|s2| <= 10^2。
- Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 1 <= |s1|,|s2| <= 10^6,s1, s2 中均只含大写英文字母。

解题思路

KMP算法是两个字符串比较的优化算法,过程比较复杂,但理解起来比较困难,我花了整整半天都在看KMP,还是看的一知半解。

代码

#include 
#include 
using namespace std;
char g[1000100];
char j[1000100];
int ne[1000100];
int main()
{
    int x,y,z,l;
    int len,len2;
    scanf("%s%s",g+1,j+1);
    len=strlen(g+1);
    len2=strlen(j+1);
    for(x=2;x<=len2;x++)
    {
        y=ne[x-1];
        while(y&&j[y+1]!=j[x])y=ne[y];
        if(j[y+1]==j[x])
            ne[x]=y+1;
        else
            ne[x]=0;
    }
    y=0;
    for(x=1;x<=len;x++)
    {
        while(y&&g[x]!=j[y+1])y=ne[y];
        if(g[x]==j[y+1])
            y+=1;
        if(y==len2)
            {printf("%d\n",x-len2+1);y=ne[y];}
    }
    for(x=1;x<=len2;x++)
        printf("%d ",ne[x]);
    return 0;
}

# Before an Exam

## 题面翻译

### 题目背景

明天皮特将要考生物。他并不很喜欢生物,但在 d 天前他得知他将不得不参加此次考试。皮特严厉的父母勒令他立即复习,因此他在第 i 天将需要学习不少于 minTime_i 小时,不多于 maxTime_i 小时。他们同时警告皮特:考试前一天,他将被检查他复习的完成情况。

因此,今天皮特的父母会要求他展示他考前复习的学习时间表。然而,他只记录这 d 天以来他复习所用的总计用时 sumTime(小时).现在他希望知道他能否给他的父母展示一份时间表,包含 d 个数,每个数 schedule_i 表示皮特第 i 天在复习生物上的用时(单位为小时),并应满足上文提及的要求。

### 题目输入

第一行包含两个数:d,sumTime。

(1<= d<=30,0<= sumTime<=240),意义如上所述。

接下来 d 行,每行两个数:minTime_i,maxtime_i,两个数之间有一个空格,意义如上。(0<= minTime_i<= maxTime_i<=8)

### 题目输出

如果有解,在单独一行输出 `YES`,换行,输出任意一种满足上文要求的解。如果无解,在单独一行中输出 `NO`。

## 样例 #1

### 样例输入 #1

```
1 48
5 7
```

### 样例输出 #1

```
NO
```

## 样例 #2

### 样例输入 #2

```
2 5
0 1
3 5
```

### 样例输出 #2

```
YES
1 4
```

解题思路

先判断能否完成,然后按每天最少去算,多出来的加到每天里,但最多不能超过每天规定的最大值。

代码

#include 
using namespace std;
int main()
{
    int d,sum,mi=0,ma=0,x,y;
    int g[50][2];
    scanf("%d%d",&d,&sum);
    for(x=0;x0)
            {
                y=0;
                if(g[x][1]-g[x][0]

你可能感兴趣的:(学习,算法)