2020牛客寒假算法基础集训营1
2020牛客寒假算法基础集训营1
| 题号 | 标题 | 已通过代码 | 题解 | 讨论 |
|---|---|---|---|---|
| A | honoka和格点三角形 | 点击查看 | 进入题解 | 进入讨论 |
| B | kotori和bangdream | 点击查看 | 进入题解 | 进入讨论 |
| C | umi和弓道 | 点击查看 | 进入题解 | 进入讨论 |
| D | hanayo和米饭 | 点击查看 | 进入题解 | 进入讨论 |
| E | rin和快速迭代 | 点击查看 | 进入题解 | 进入讨论 |
| F | maki和tree | 点击查看 | 进入题解 | 进入讨论 |
| G | eli和字符串 | 点击查看 | 进入题解 | 进入讨论 |
| H | nozomi和字符串 | 点击查看 | 进入题解 | 进入讨论 |
| I | nico和niconiconi | 点击查看 | 进入题解 | 进入讨论 |
E
每个数字分解质因数
计算x的素因子个数 j,向下模拟
12 = 1 2 3 4 6 12
6 = 1 2 3 6
4 = 1 2 4
3 = 1 3
分解到最后只有两个因子 即为答案
/*************************************************************************
> File Name: e.cpp
> Author:
> Mail:
> Created Time: 二 2/ 4 13:21:35 2020
************************************************************************/
#include<bits/stdc++.h>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
ll sovle(ll n){
ll i = 0,j = 0;
for(i = 1;i * i < n; i++){
if(n % i == 0){
j += 2;
}
}
if(i * i == n)j++; //f(3) = 1 // 1 * 1 = 1
return j;
}
int main(int argc, char *argv[]) {
SIS;
ll n;
cin >> n;
ll sum = 0;
while(n != 2){
sum++;
n = sovle(n);
}
cout << sum << endl;
return 0;
}
F
题目要求任意取两点,只经过一个黑点的取法有多少种
- 两个端点都是白点
- 其中一个端点是黑点
预处理将每个白点联通块上的白点个数统计出来,这样我们知道,每个黑点连接了多少个白点
假设某黑点连接了k个白点,第i个白点的权值为f(i)
G
单独处理每种字符找k个的长度(双指针),求最小值
至少包含k个相同的字母, 那么代表肯定会有相同字母出现,但是我们并不知道这些字母最短的长度是多少,所以我们使用双指针来求得最短长度
如何处理呢,我们将每种字符的数量存入数组,同时遍历字符串;
在遍历的过程中,会出现当前字符的数量 == k,这时,我们就可以移动左指针,同时排除前面字符的干扰
什么意思呢,拿样例举例:
k = 2
abeba 我们得到的最短长度是3,假设为abecd...这样,我们可以知道,最短距离一定出现在 d字符的后面(abecdd.....),那么d字符前面的所有字符与后面相同字符串组成的长度一定大于 (abecdd..)这样组成的最短长度
假设我们在代码中不减去记录该数量的字符,我们会得到一个错误的解答
例如abced......dd
那么我们枚举到第三个d 的时候,我们发现b[’d'] 的值永远大于k 我们也无法枚举到最短长度的字符串. 我们只需要k个即可,不需要大于k的
/*************************************************************************
> File Name: g.cpp
> Author:
> Mail:
> Created Time: 二 2/ 4 13:37:07 2020
************************************************************************/
#include<bits/stdc++.h>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
int num = 0,tmplen;
int minx = 0x3f3f3f3f;
string s;
int ans = minx;
int b[26];
int main(int argc, char *argv[]) {
SIS;
int n;
int m;
cin >> n >> m;
cin >> s;
int r,l;
for( r = 0; r < n; r++){
int t = s[r] - 'a';
++b[t]; // 记录字母
if(b[t] == m) // 如果当前字母数量 == 我们需要的
{
while(l < r && s[l] != s[r])--b[s[l] - 'a'],++l;
ans = min(ans, r - l + 1);
--b[s[l] - 'a'];
++l;
}
}
if(ans == minx){
ans = -1;
}
cout << ans << endl;
return 0;
}
H
两种方法:
- 第一种
全1变0 或者 全0变1, 分别处理两种操作,对于1变0,可以分别统计
- 1的前缀1,后缀1的位置(第一个1的前缀1的位置为0,最后一个1的位置为n + 1
- k次操作,即变换连续k个1,最终的字符串长度就是第i个1的前缀1,到第i + k个后缀1之间到距离
#include<bits/stdc++.h>
using namespace std;
string s;
vector<int>v0,v1; //v0存字符'0'的坐标位置,v1存字符'1'的坐标位置
int main(){
int n,k,i,j;
cin>>n>>k;
cin>>s;
v0.push_back(-1);
v1.push_back(-1);
for(i=0;i<n;i++){
if(s[i]=='0')v0.push_back(i);
else v1.push_back(i);
}
v0.push_back(n);
v1.push_back(n);
int ma=0;
if(v0.size()-2<=k)ma=n;
else{
for(i=1,j=k;j<v0.size()-1;i++,j++){
ma=max(ma,v0[j+1]-v0[i-1]-1);
cout << (v0[j+1]-v0[i-1]-1) << endl;
}
}
if(v1.size()-2<=k)ma=n;
else{
for(i=1,j=k;j<v1.size()-1;i++,j++){
ma=max(ma,v1[j+1]-v1[i-1]-1);
}
}
cout<<ma;
}
/*************************************************************************
> File Name: test.cpp
> Author:
> Mail:
> Created Time: 二 2/ 4 17:37:45 2020
************************************************************************/
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
string str;
cin>>str;
vector<int> Hash(2,0);
int res = 0, maxNum = 0;
for(int i=0,j=0;j<str.size();j++){
Hash[str[j]-'0']++;
maxNum = max(maxNum, Hash[str[j]-'0']);
while(j-i+1-maxNum>m)
Hash[str[i++]-'0']--;
res = max(res,j-i+1);
}
cout<<res<<endl;
}
I
转移方程

#include<bits/stdc++.h>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 300005;
ll dp[maxn] = {0};
#define max(x, y) (x) > (y) ? (x) : (y)
string a;
int main(int argc, char *argv[]) {
SIS;
ll i,n,x,y,z;
cin>>n>>x>>y>>z;
cin>>a;
for(i=0;i<n;i++){
if(i>0)dp[i]=dp[i-1];
if(i>=3&&a[i-3]=='n'&&a[i-2]=='i'&&a[i-1]=='c'&&a[i]=='o')
dp[i]=max(dp[i],dp[i-3]+x);
if(i>=5&&a[i-5]=='n'&&a[i-4]=='i'&&a[i-3]=='c'&&a[i-2]=='o'&&a[i-1]=='n'&&a[i]=='i')
dp[i]=max(dp[i],dp[i-5]+y);
if(i>=9&&a[i-9]=='n'&&a[i-8]=='i'&&a[i-7]=='c'&&a[i-6]=='o'&&a[i-5]=='n'&&a[i-4]=='i'&&a[i-3]=='c'&&a[i-2]=='o'&&a[i-1]=='n'&&a[i]=='i')
dp[i]=max(dp[i],dp[i-9]+z);
}
cout << dp[n - 1] << endl;
return 0;
}

浙公网安备 33010602011771号