牛客练习赛74AB
A CCA的数列
题目
链接:https://ac.nowcoder.com/acm/contest/9700/A
来源:牛客网
题目描述
给定一个长度为 n 数列,判断其是否为“牛”的,是则输出“YES”,否则输出“NO”。
一个数列是“牛”的,当且仅当其满足以下三个条件中至少一个:
1、这个数列是等差数列
2、这个数列是等比数列
3、这个数列是等模数列。
等差数列和等比数列的定义如果不清楚建议百度或重上小学(划掉),等模数列的定义是:对于任意相邻两数,后一个对前一个取模后的值均相等。
输入描述:
第一行一个整数 n。
第二行 n 个整数,分别表示这个数列的值。
输出描述:
一行,一个单词“YES”或“NO”(不含引号)。
示例1
输入
复制
5
1 2 3 4 5
输出
复制
YES
说明
此数列为等差数列。
示例2
输入
复制
3
5 7 16
输出
复制
YES
说明
此数列为等模数列。
备注:
3 <= n <= 10^5,1 <= 数列中的每个数<=10^9
题意
符合等比数列等差数列等mod数列就是“牛”的数列 问给定数列是否为牛数列
思路
直接比较即可,很坑的地方是 等比数列必须考虑到公比不是整数的情况,但是也不能用double存因为后面要取模
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000+100;
int a[maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int f1 = 1,f2 = 1,f3 = 1;
int b = a[2] - a[1];
for(int i=3;i<=n;i++)
{
if(a[i]-a[i-1]!=b)
{
f1 = 0;
break;
}
}
if(f1)
return cout<<"YES",0;
double c = a[2]*1.0/a[1]*1.0;
// cout<<c<<endl;
for(int i=3;i<=n;i++)
{
if(1.0*a[i]/a[i-1]*1.0!=c)
{
// cout<<i<<" "<<1.0*a[i]/1.0*a[i-1]<<endl;
f2 = 0;
break;
}
}
if(f2)
return cout<<"YES",0;
int d = a[2]%a[1];
for(int i=3;i<=n;i++)
{
if(a[i]%a[i-1]!=d)
{
f3 = 0;
break;
}
}
if(f3)
return cout<<"YES",0;
cout<<"NO";
}
B CCA的字符串
题目
链接:https://ac.nowcoder.com/acm/contest/9700/B
来源:牛客网
题目描述
给定一个仅由大写字母和小写字母组成的字符串。
一个字符串是“牛”的,当且仅当其有一个子串为“NowCoder”(区分大小写)。
问给定字符串有多少个子串是“牛”的。
输入描述:
一行,一个字符串。
输出描述:
一行,一个数表示答案。
示例1
输入
复制
NowCoderNowCode
输出
复制
8
备注:
字符串长度<=10^5
题意
给定一个字符串 定义“牛”的字符串当且仅当其有一个子串为“NowCoder”
这里非常需要注意的是 当且仅当有一个子串为“NowCoder”的意思是,只要有一个子串是“NowCoder”就可以,两个连着的也行!!!打比赛的时候吃了语文的亏还行,题面也改了三次 从子串改成子序列又改成子串 有点迷惑
思路1
查询当前下一个“NowCoder”的位置,用len - position - 8 + 1 (-8的意思是去掉“NowCoder”这一段,+1代表着算上“NowCoder”自己) 再减去当前的位置,由于i是往后递增的,所以position是递减的,这时候由于前面算过了 所以要减去i
代码1
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin>>s;
int len = s.size();
int cnt = 0;
long long ans = 0;
for(int i=0;i<len-7;i++)
{
// string now = "";
// for(int j=i;j<i+8;j++)
// now += s[j];
long long cnt = s.substr(i).find("NowCoder");
// cout<<cnt<<endl;
if(cnt == -1) break;
ans += len - 8 + 1 - i - cnt;
// cout<<ans<<endl;
}
cout<<ans;
return 0;
}
/*
NowCoderNowCoder
*/
思路2
学习牛客网上同仁写的 并加深了理解
考虑代表元计数法,把每个子串的贡献记录在最靠左的 NowCoder 上。
设 \([i, i + 7]\) 这一段是 NowCoder,lastlast 为上一个 NowCoder 左端点的位置,可取的左端点范围是 \([last + 1, i]\),右端点是 \([i + 7, n]\),对答案的贡献即 \((i - last) \times (n - (i + 7) + 1)\)。
代码2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
string s;
cin>>s;
s = "+" + s;
ll len = s.size();
len--;
ll cnt = 0;
ll ans = 0;
ll last = 0;
// cout<<len<<endl;
for(int i=1;i<=len-7;i++)
{
string now = "";
for(int j=i;j<i+8;j++)
now += s[j];
if(now=="NowCoder")
{
// cout<<i<<endl;
ans += (i - last) * (len - (i+7) + 1LL);
last = i;
}
}
cout<<ans;
return 0;
}
/*
NowCoderNowCoder
*/