牛客练习赛74

题目

链接:https://ac.nowcoder.com/acm/contest/9700/A
来源:牛客网

题目描述

给定一个长度为 n 数列,判断其是否为“牛”的,是则输出“YES”,否则输出“NO”。

一个数列是“牛”的,当且仅当其满足以下三个条件中至少一个:

1、这个数列是等差数列

2、这个数列是等比数列

3、这个数列是等模数列。

等差数列和等比数列的定义如果不清楚建议百度或重上小学(划掉),等模数列的定义是:对于任意相邻两数,后一个对前一个取模后的值均相等。

输入描述:

第一行一个整数 n。
第二行 n 个整数,分别表示这个数列的值。

输出描述:

一行,一个单词“YES”或“NO”(不含引号)。

示例1

输入

[复制](javascript:void(0)😉

5
1 2 3 4 5

输出

[复制](javascript:void(0)😉

YES

说明

此数列为等差数列。

示例2

输入

[复制](javascript:void(0)😉

3
5 7 16

输出

[复制](javascript:void(0)😉

YES

说明

此数列为等模数列。

备注:

3 <= n <= 10^5,1 <= 数列中的每个数<=10^9

分析

模拟了事

代码

#include <iostream>

using namespace std;

const int N = 100010;

int n;
double a[N];
bool x, y, z;

int main() {
  cin >> n;
  cin >> a[0] >> a[1];
  for (int i = 2; i < n; i ++ ) {
    scanf("%lf", &a[i]);
    //判断是否为等差
    int d = a[1] - a[0];
    if (a[i] - a[i - 1] != d) x = true;
    //判断是否为等比
    double q = a[1] / a[0];
    if (a[i] / a[i - 1] != q) y = true;
    //判断时候为等模
    int m = (int)a[1] % (int)a[0];
    if ((int)a[i] % (int)a[i - 1] != m) z = true;
  }

  if (!x || !y || !z) puts("YES") ;
  else puts("NO");

  return 0;
}

CCA的字符串

题目

链接:https://ac.nowcoder.com/acm/contest/9700/B
来源:牛客网

题目描述

给定一个仅由大写字母和小写字母组成的字符串。

一个字符串是“牛”的,当且仅当其有一个子串为“NowCoder”(区分大小写)。

问给定字符串有多少个子串是“牛”的。

输入描述:

一行,一个字符串。

输出描述:

一行,一个数表示答案。

示例1

输入

[复制](javascript:void(0)😉

NowCoderNowCode

输出

[复制](javascript:void(0)😉

8

备注:

字符串长度<=10^5

分析

考虑代表元计数法,把每个字串的贡献记录在最靠左的NowCoder上。设[i, i + 7]这一段是NowCoder,last为上一个NowCoder左端点的位置,可取得左端点范围是[last + 1, i],右端点是[i + 7, n],对答案得贡献即(i - last) * (n - (i + 7) + 1)

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
	string a;
	cin>>a;
  long long ans=0;
  long long t=0;
  int last=-1;
  /*
  我就好奇了,这个代码是怎么AC的???
   */
	for(int i=0;i<a.length();i++)
	{
		if(a[i]=='N'&&a[i+1]=='o'&&a[i+2]=='w'&&a[i+3]=='C'&&a[i+4]=='o'&&a[i+5]=='d'&&a[i+6]=='e'&&a[i+7]=='r')
		{
      //cout << a[i] << "-----------" << ans << endl;
			ans=ans+(i-last)*(a.length()-i-7);
			last=i;
		}
	}
	printf("%lld\n",ans);
}

CCA的矩阵

题目

链接:https://ac.nowcoder.com/acm/contest/9700/C
来源:牛客网

题目描述

很久很久以后的某一天,老鼠泛滥成灾啦!

有某一个 n×n 的矩形内布满了老鼠,具体来说,(i,j) 上有 w(i,j)只老鼠。

万幸的是,你有一个 k×k 的锤子,一锤子砸下去可以把它覆盖到的所有老鼠清除。

遗憾的是,这个锤子只能斜着锤,形象地说,对于一个 3×3 的锤子,它能覆盖到的区域如下:

- - * - -

- * * * -

* * * * *

- * * * -

- - * - -

你想知道,自己一锤子砸下去,最多能清除多少只老鼠。

输入描述:

第一行两个数 n和k 。
之后的 n 行,每行 n 个数,第 i 行 第 j 个数表示在矩形的这个位置有多少只老鼠。

输出描述:

一行,一个整数表示最多能清除的老鼠数量。

示例1

输入

[复制](javascript:void(0)😉

3 2
0 1 1
1 0 1
0 1 0

输出

[复制](javascript:void(0)😉

4

备注:

n <= 2000 , k <= min(n, 100),每个点的老鼠数量 <= 10^9

分析

墨染空大佬的代码,我是还没分析出来,留到以后水平高了后再来做

墨染空大佬的代码

/*
 *@author SunLakeWalk
 */
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inlin")

using namespace std;

#define ios ios::sync_with_stdio(false) , cin.tie(0)
#define x first
#define y second

typedef long long LL;
typedef pair<int, int> PII;

const int N = 2010, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, pi = acos(-1);
int n, k;
LL s[N][N], a[N][N], b[N][N], c[N][N];
LL ans;
/*
我们可以发现这是一个斜着的前缀和,这里是墨染空巨佬的做法。
通过观察,发现菱形区域可以看作斜着的正方形。
正方形里面包含了k个k长度的序列和k-1个k-1长度的序列。
我们分别用a和b数组来存储斜的前缀和。
斜着的前缀和只由它的(i-1,j-1)转移过来的
 */
void work() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++ )
      for (int j = 1; j <= n; j ++ )
        scanf("%lld", &s[i][j]);

        /*
        让s存入数据,让a记录长度为k的,斜前缀和
        让b记录长度为k - 1的,斜前缀和
        让c记录以(i,j)为最下面的那个点所在的菱形的长宽为k的斜前缀和,即我们的答案
        */
    for (int i = 1; i <= n; i ++ )
      for (int j = 1; j <= n; j ++ ) {
        a[i][j] = a[i - 1][j - 1] + s[i][j];
        if (i > k && j > k) a[i][j] -= s[i - k][j - k];//维护长度为k
        b[i][j] = b[i - 1][j - 1] + s[i][j];
        if (i > k - 1 && j > k - 1) b[i][j] -= s[i - k + 1][j - k + 1];//维护长度为k-1
      }

    for (int i = 1; i <= n; i ++ )
      for (int j = 1; j <= n; j ++ ) {
        /*

         */
        c[i][j] = c[i - 1][j + 1] + a[i][j] + b[i - 1][j] - a[i - k][j + k] - b[i - k][j + k - 1];
        if (j + k - 1 <= n && j - k + 1 >= 1 && i - (2 * k - 1) + 1 >= 1) ans = max(ans, c[i][j]);
      }
    cout << ans << endl;
}

int main() {

  work();

  return 0;
}

多次打印墨染空大佬的代码

/*
 *@author SunLakeWalk
 */
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inlin")

using namespace std;

#define ios ios::sync_with_stdio(false) , cin.tie(0)
#define x first
#define y second

typedef long long LL;
typedef pair<int, int> PII;

const int N = 100010, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, pi = acos(-1);

int n = 5, k = 2;
int a[100][100], s[100][100], b[100][100], c[100][100];
int ans = 0;

void print(int a[100][100]) {
  for (int i = 1; i <= n; i ++ ) {
      for (int j = 1; j <= n; j ++ )
          printf("%d ", a[i][j]);
      puts("");
  }
  puts("----------------------");
}

void work() {
  for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= n; j ++ )
      s[i][j] = i;

  print(s);

  for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= n; j ++ ) {
      a[i][j] = s[i][j] + a[i - 1][j - 1];
      if (i > k && j > k) a[i][j] -= s[i - k][j - k];
    }

  print(a);

  for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= n; j ++ ) {
      b[i][j] = s[i][j] + b[i - 1][j - 1];
      if (i > k - 1 && j > k - 1) b[i][j] -= s[i - k + 1][j - k + 1];
    }

  print(b);

  for (int i = 1; i <= n; i ++ )
    for (int j = 1; j <= n; j ++ ) {
      c[i][j] = c[i - 1][j + 1] + a[i][j] + b[i - 1][j] - a[i - k][j + k] - b[i - k][j + k - 1];
      if (j + k - 1 <= n && j - k + 1 >= 1 && i - (2 * k - 1) + 1 >= 1) ans = max(ans, c[i][j]);
    }
    
  print(c);

  cout << ans << endl;
}

int main() {

  work();

  return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值