题目链接
补题挖坑
A
凡是有2的因子的全提出来,之后排序乘给最大的奇数
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
ll t, n;
int main()
{
cin >> t;
while (t--)
{
cin >> n;
vector<ll> a(n);
for (auto &i : a)
cin >> i;
int ans = 0;
for (int i = 0; i < a.size();i++)
{
while(a[i]%2==0)
{
ans += 1;
a[i] /= 2;
}
}
sort(a.begin(), a.end());
ll sum = 0;
for (int i = 0; i < a.size() - 1;i++)
{
sum += a[i];
}
sum += a[n - 1] * pow(2, ans);
cout << sum << endl;
}
return 0;
}
B
感觉写麻烦了,但大意就是匹配到了abc就ans++,没匹配到的话就ans不变,ans是开始遍历计算的abc数量
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
ll t, n;
int main()
{
cin >> n >> t;
string s;
cin >> s;
int ans = 0;
for (int i = 0; i < n - 2;)
{
if (s[i] == 'a' && s[i + 1] == 'b' && s[i + 2] == 'c')
{
ans++;
i += 3;
}
else
{
i++;
}
}
s = "0" + s + "0";
while (t--)
{
char c;
int pos;
scanf("%d %c", &pos, &c);
if (c == s[pos])
{
cout << ans << endl;
continue;
}
bool flag = true;
if (s[pos] == 'a' && s[pos + 1] == 'b' && s[pos + 2] == 'c' && pos <= n - 2)
{
if (c != 'a')
ans--;
}
else if (s[pos - 1] == 'a' && s[pos] == 'b' && s[pos + 1] == 'c')
{
if (c != 'b')
ans--;
}
else if (s[pos - 2] == 'a' && s[pos - 1] == 'b' && s[pos] == 'c' && pos >= 2)
{
if (c != 'c')
ans--;
}
if (c == 'a' && s[pos + 1] == 'b' && s[pos + 2] == 'c' && pos <= n - 2)
{
ans++;
}
else if (s[pos - 1] == 'a' && c == 'b' && s[pos + 1] == 'c')
{
ans++;
}
else if (s[pos - 2] == 'a' && s[pos - 1] == 'b' && c == 'c' && pos >= 2)
{
ans++;
}
cout << ans << endl;
s[pos] = c;
}
return 0;
}
C
规定了间隙e,所以就是找素数,找到之后看看间隙左右的1的个数,左边是back,右边是back
只考虑单侧那就back+front
考虑左右两边就back*front
最后加和输出,但是要记得longlong
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
ll t, n, e;
int isPrime(int n)
{
if (n <= 1)
{
return 0;
}
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
}
int main()
{
cin >> t;
while (t--)
{
cin >> n >> e;
vector<ll> a(n);
for (auto &i : a)
cin >> i;
ll ans = 0;
for (int i = 0; i < n; ++i)
{
if (isPrime(a[i]))
{
ll _front = 0, _back = 0;
for (int j = i + e; j < n; j += e)
if (a[j] == 1)
_front++;
else
break;
for (int j = i - e; j >= 0; j -= e)
if (a[j] == 1)
_back++;
else
break;
ans += (_front + _back);
ans += (_front * _back);
}
}
cout << ans << endl;
}
return 0;
}
D
题目大意是给定n个点,针对m个边即时输出最大的连通块大小-1(题目定义的熟人)
如果有重复的边或者联通集和内部的边那就拿出来用作连接两个联通集和
用并查集维护就行
但感觉这样做很容易T,因为map倒vector,有双set的写法可以再看看
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
ll m, n;
int fa[1010];
int get(int x)
{
if (x == fa[x])
return x;
return fa[x] = get(fa[x]);
}
void merge(int x, int y)
{
fa[get(x)] = get(y);
}
bool cmp(pair<int,int> a,pair<int,int> b)
{
return a.second > b.second;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
}
int flag = 0;
int ans = 0;
for (int i = 0; i < m; ++i)
{
int x, y;
cin >> x >> y;
if (get(x) != get(y))
merge(x, y);
else
{
flag++;
}
map<int, int> M;
for (int i = 1; i <= n; ++i)
{
M[get(i)]++;
}
vector<pair<int, int>> a(M.begin(), M.end());
sort(a.begin(), a.end(), cmp);
ans = a[0].second;
for (int i = 1; i <= flag && i < a.size(); ++i)
{
ans += a[i].second;
}
cout << ans - 1 << endl;
}
return 0;
}
E
听说是线段树,不会构造阿巴阿巴
留着空挖坑