[算法学习记录] ABC401 A-E
A - Status Code
根据题意模拟即可
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
int s;cin >> s;
if(s>=200&&s<=299)cout <<"Success\n";
else cout << "Failure\n";
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}
B - Unauthorized
还是根据题意模拟
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
int n;cin >> n;
int ans = 0;
bool sta = false;
while(n--)
{
string s;cin >> s;
if(s=="login") sta = true;
if(s=="logout") sta = false;
if(s=="private"&&!sta) ans++;
}
cout << ans <<"\n";
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}
C - K-bonacci
可以用双端队列动态维护当前元素的值,也可以用前缀和解答。
双端队列
点击查看代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int p = 1e9;
vector<ll> num;
void solve()
{
ll n,k;cin >> n >> k;
if(n<k)
{
cout << 1 <<"\n";
return;
}
deque<ll> dq;
ll sum = 0;
for(int i = 0; i < k; ++i)
{
dq.push_back(1);
sum = (sum + 1) % p;
}
//预处理
for(int i = k; i <= n; ++i)
{
ll c = sum;
dq.push_back(c);
sum = (sum + c) % p;
//更新首部元素
if(dq.size() > k)
{
sum = (sum - dq.front() + p) % p;
//模运算可能会出现负数,加个p防止爆long long
dq.pop_front();
//弹出尾部元素
}
//得到新的k项和
}
cout << dq.back() << "\n";
//输出队首元素
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}
前缀和
补
点击查看代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6+5;
const ll p = 1e9;
ll a[N];
void solve()
{
int n,k;cin >> n >> k;
for(int i = 1;i<=k;i++)a[i] = a[i-1] + 1;
for(int i = k + 1;i<=n+1;i++) a[i] = (2*a[i-1] - a[i - k - 1]) % p;
//a[]数组就是前缀和数组
cout << (a[n+1] - a[n] + 2*p)%p <<"\n";
//前缀和求特定区间值(加2*p是为了防止出现负数,同时也为了满足题意)
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}
补
本题已保证X不为空,所以我们只需考虑X存在的情况即可。
因为o不能相邻,所以o两端的字符就是确定的,所以我们可以先处理o两端的字符;
这样我们就得到一个新字符串\(S'\),以及一个新条件\(k'\)。
至此,我们要做的事就变成了确定如何把\(k'\)个o放入若干个由?构成的区间区间中;
假设每一个区间的长度为\(l_i\),那么每一个区间最多可以容纳的o的个数为\(\lceil \frac {l_i}{\over2} \rceil\)
该字符串所能容纳o的最大数量为\(\sum_{i=1}^{m} l_i\),其中\(m\)为符合条件的区间的数量。
由于X一定存在,所以$ cnt\leq k$
当\(k=0\)时,所有的?就只能是.,只有一种可能;
当\(k=cnt\)时,分两种情况;
- 若\(cnt\)为奇数,那么就只有形如
o.o.o的一种可能 - 若\(cnt\)为偶数,那么就有两种可能一种是
.o.o.o另一种是o.o.o.,每个位置都不能确定,所有的?依然是?;
当\(k \not= cnt\)时,\(k<cnt\)说明至少有一个区间没有o,\(k>0\)说明至少有一个区间非空,也就是说每一个位置都无法确定,所以全部都是?。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int cnt = 0;
void solve()
{
int n,k;cin >> n >> k;
string s;cin >> s;s = "#" + s + "#";
//读入字符串,在前后各加一个不相干的字符以简化算法
for(int i = 1;i<=n;i++)
if(s[i]=='o')
{
s[i-1] = '.';s[i+1] = '.';
k--;
}
//把o的前后都标记为.
for(int i = 1,l = 0;i<=n;i++)
{
if(s[i]=='?'&&s[i-1]!='?') l = i;
if(s[i]=='?'&&s[i+1]!='?') cnt += (i-l)/2+1;
}
//计算该字符串k出现的最多次数(不算初始的)
if(!k) for(int i = 1;i <= n;i++)if(s[i]=='?') s[i] = '.';
//k=0的情况
if(k==cnt)
{
for(int i = 1,l = 0;i<=n;i++)
{
if(s[i]=='?'&&s[i-1]!='?')l = i;
if(s[i]=='?'&&s[i+1]!='?')
{
if((i-l+1)&1)
//?串的长度为奇数,为偶数时不能确定
for(int j = l;j<=i;j++)
((j-l+1)&1) ? s[j] = 'o' : s[j] = '.';
//偶数位为o,奇数位为.
}
}
}
//k=cnt的情况
for(int i = 1;i<=n;i++)cout << s[i];
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}
E - Reachable Set
补
根据题目描述,可以看出本题可以用并查集解决。
遍历\(1\)~\(k\),
如果存在答案,那么所有的节点都是联通的,也就是说联通块只有一个,我们可以用一个变量\(cnt\)来表示联通块的个数;
如果要符合答案的条件,那么比\(k\)大的点就一定要被删去(只删去与之直接相连的即可),这样计算得出的答案一定是最小值。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5+5;
int n,m,pre[N],cnt,ans;
bitset<N> vis;
vector<int> g[N];
int root(int u)
{
return pre[u] = (pre[u] == u ? u : root(pre[u]));
}
void merge(int u,int v)
{
int x = root(u),y = root(v);
if(pre[x]!=y)pre[x] = y,cnt--;
}
void solve()
{
cin >> n >> m;
while(m--)
{
int u,v;cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1;i<=n;i++)pre[i] = i;
for(int i = 1;i<=n;i++)
{
cnt++;
if(vis[i]) ans--;
//记得忽略k点本身
for(auto &p : g[i])
{
if(p<i) merge(i,p);
else if(!vis[p]) vis[p] = true,ans++;
}
cout << (cnt == 1 ? ans : -1) <<"\n";
//如果只有一个联通块就符合条件
}
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _ = 1;
while(_--)solve();
return 0;
}

浙公网安备 33010602011771号