A. 宇宙的终结
暴力找 [ 1 , 100 ] [1,100] [1,100]中的三个素数乘积,时间复杂度 O ( n 3 l o g n ) O(n^3logn) O(n3logn)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int pd(int x)
{
for(int i = 2;i <= sqrt(x);i++)
{
if(x % i == 0)
return 0;
}
return 1;
}
void solve()
{
int l, r;
cin >> l >> r;
for(int i = 2;i <= 100;i++)
{
for(int j = i + 1;j <= 100;j++)
{
for(int k = j + 1;k <= 100;k++)
{
if(pd(i) && pd(j) && pd(k) && i * j * k >= l && i * j * k <= r)
{
cout << i * j * k << '\n';
return;
}
}
}
}
cout << "-1" << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
B. 爱恨的纠葛
先使一个数组有序,然后对于另一个数组中的每个元素,二分找到与它最接近的那个值,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int a[N], b[N];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
cin >> a[i];
for(int i = 1;i <= n;i++)
cin >> b[i];
sort(a+1,a+n+1);
int t1, t2, ans = INF;
for(int i = 1;i <= n;i++)
{
int l = 1, r = n;
int res = INF, pos;
while(l <= r)
{
int mid = (l + r) / 2;
if(a[mid] > b[i])
r = mid - 1;
else
l = mid + 1;
if(abs(a[mid] - b[i]) < res)
{
res = abs(a[mid] - b[i]);
pos = mid;
}
}
if(res < ans)
{
ans = res;
t1 = i;
t2 = pos;
}
}
swap(a[t1], a[t2]);
for(int i = 1;i <= n;i++)
cout << a[i] << " ";
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
C. 心绪的解剖
1 0 9 10^9 109以内的斐波那契数不超过五十个,可以直接暴力查找,时间复杂度 O ( 50 n ) O(50n) O(50n)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int f[N];
void solve()
{
int m = 0;
f[0] = 0;
f[1] = 1;
for(int i = 2;i <= 1e6;i++)
{
f[i] = f[i - 1] + f[i - 2];
if(f[i] > 1e9)
{
m = i;
break;
}
}
f[1] = 0;
int q;
cin >> q;
while(q--)
{
int n;
cin >> n;
int cnt = 0;
vector<int> ans;
for(int i = m;i >= 1;i--)
{
if(f[i] <= n)
{
ans.push_back(f[i]);
n -= f[i];
cnt++;
i++;
}
if(cnt == 3)
break;
}
if(n == 0)
{
for(auto u : ans)
cout << u << " ";
cout << '\n';
}
else
cout << "-1" << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
D. 友谊的套路
小红让二追三和被让二追三两种情况的概率之和,时间复杂度 O ( 1 ) O(1) O(1)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
void solve()
{
double p;
cin >> p;
double t1 = 1, t2 = 1;
t1 = t1 * (1 - p) * (1 - p) * p * p * p;
t2 = t2 * p * p * (1 - p) * (1 - p) * (1 - p);
double ans = t1 + t2;
cout << fixed << setprecision(6) << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
E. 未来的预言
遍历字符串,看哪只队伍先达到预期局数,时间复杂度 O ( x ) O(x) O(x)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
void solve()
{
string s;
cin >> s;
int now = 0;
for(int i = 2;i < s.size();i++)
now = now * 10 + s[i] - '0';
now = now / 2 + 1;
string ss;
cin >> ss;
int t1 = 0, t2 = 0;
for(int i = 0;i < ss.size();i++)
{
if(ss[i] == 'R')
t1++;
else
t2++;
if(t1 == now)
{
cout << "kou!" << '\n';
cout << t1 + t2 << '\n';
return;
}
else if(t2 == now)
{
cout << "yukari!" << '\n';
cout << t1 + t2 << '\n';
return;
}
}
cout << "to be continued." << '\n';
cout << t1 + t2 << '\n';
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
F. 命运的抉择
并查集,从第一个数开始,找其他元素中含有相同因子的数,如果找到则加入并查集,值得注意的是,每次找完某个因子要及时清空,不然最后一起清空的时候会超时,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
(我说比赛的时候时间被卡的这么厉害,原来是我菜)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
vector<vector<int> > p(1e6 + 10);
int a[N];
void solve()
{
int n;
cin >> n;
vector<int> x, y, vis(n + 5);
vector<vector<int> > pri(n + 1);
for(int ii = 1;ii <= n;ii++)
{
cin >> a[ii];
if(a[ii] == 1)
{
pri[ii].push_back(1);
p[1].push_back(ii);
continue;
}
int j = a[ii];
for(int i = 2;i <= j / i;i++)
{
if(j % i == 0)
{
pri[ii].push_back(i);
p[i].push_back(ii);
while(j % i == 0)
j /= i;
}
}
if(j > 1)
{
pri[ii].push_back(j);
p[j].push_back(ii);
}
}
// for(int i = 1;i <= n;i++)
// {
// for(auto u : pri[i])
// {
// cout << u << '\n';
// for(auto q : p[u])
// cout << q << " ";
// }
// cout << '\n';
// }
queue<int> q;
q.push(1);
vis[1] = 1;
while(!q.empty())
{
int k = q.front();
q.pop();
for(auto i : pri[k])
{
for(auto j : p[i])
{
if(!vis[j])
{
q.push(j);
vis[j] = 1;
}
}
p[i].clear();
}
}
for(int i = 1;i <= n;i++)
{
if(vis[i])
x.push_back(a[i]);
else
y.push_back(a[i]);
}
if(y.size() == 0)
cout << "-1 -1" << '\n';
else
{
cout << x.size() << " " << y.size() << '\n';
for(auto u : x)
cout << u << " ";
cout << '\n';
for(auto u : y)
cout << u << " ";
cout << '\n';
}
for(int i = 1;i <= n;i++)
{
for(auto u : pri[i])
p[u].clear();
pri[i].clear();
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
G. 人生的起落
先构造一个形如 2121212... 2121212... 2121212...的数组,如果达到 k k k个后用 1 1 1填补。如果构造完都没达到 k k k的个数要求或者构造完后总数大于 S S S则不行
构造完之后,记差值 c c c为 s u m − S sum - S sum−S,如果最后一个 2 2 2不在 n n n的位置上,那我们就把 c c c全加在后面的某个 1 1 1上,如果在 n n n的位置上,要看 c c c是否能让每个 2 2 2至少分到 1 1 1,如果可以,那么无论如何也能构造成功,因为平均分给每个 2 2 2后,多出来的部分可以再分摊给里面的 1 1 1,只要保证加完后的 1 1 1不超过其两边的数字即可,时间复杂度 O ( n ) O(n) O(n)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int ans[N];
void solve()
{
int n, s, k;
cin >> n >> s >> k;
int cnt = 0, pos = 1;
for(int i = 1;i <= n;i++)
{
if(k == 0)
{
ans[i] = 1;
cnt++;
}
else
{
if(i % 2 == 1)
{
ans[i] = 2;
if(i > 1)
k--;
if(k == 0)
pos = i;
}
else
ans[i] = 1;
cnt += ans[i];
}
}
if(k > 0)
{
cout << "-1" << '\n';
return;
}
if(cnt > s)
{
cout << "-1" << '\n';
return;
}
if(pos == n)
{
int c = s - cnt;
if(c < n / 2 + 1 && c > 0)
{
cout << "-1" << '\n';
return;
}
int tt = c / (n / 2 + 1);
int sy = c - tt * (n / 2 + 1);
for(int i = n;i >= 1;i--)
{
if(i % 2 == 1)
ans[i] += tt;
else
{
int jia = min(sy, tt);
ans[i] += jia;
sy -= jia;
}
}
}
else
ans[pos + 1] += s - cnt;
for(int i = 1;i <= n;i++)
cout << ans[i] << " ";
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
I. 时空的交织
分别求出 a a a数组和 b b b数组的最大连续子串和和最小连续子串和,答案就是两两相乘中的最大值,时间复杂度 O ( n ) O(n) O(n)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int a[N], b[N];
void solve()
{
int n, m;
cin >> n >> m;
for(int i = 1;i <= n;i++)
cin >> a[i];
for(int i = 1;i <= m;i++)
cin >> b[i];
int mx1 = a[1], mn1 = a[1];
int res = 0;
for(int i = 1;i <= n;i++)
{
res += a[i];
mx1 = max(mx1, res);
if(res < 0)
res = 0;
}
res = 0;
for(int i = 1;i <= n;i++)
{
res += a[i];
mn1 = min(mn1, res);
if(res > 0)
res = 0;
}
//cout << mx1 << " " << mn1 << '\n';
int mx2 = b[1], mn2 = b[1];
res = 0;
for(int i = 1;i <= m;i++)
{
res += b[i];
mx2 = max(mx2, res);
if(res < 0)
res = 0;
}
res = 0;
for(int i = 1;i <= m;i++)
{
res += b[i];
mn2 = min(mn2, res);
if(res > 0)
res = 0;
}
//cout << mx2 << " " << mn2 << '\n';
int t1 = max(mx1 * mx2, mx1 * mn2);
int t2 = max(mn1 * mn2, mn1 * mx2);
cout << max(t1, t2) << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
J. 绝妙的平衡
如果一个红色节点的孩子中没有白色节点,说明除了它自己以外的子树节点之和为 3 3 3的倍数,如果再加上它自己,那一定不是 3 3 3的倍数,不符合题意
一开始先给所有节点的权值都赋值为 2 2 2,从叶子结点开始,统计当前节点的子树权值之和,如果当前节点为红色,则进行判断
1. 1. 1.子树权值 % 3 = 0 \%3=0 %3=0,符合题意,不做修改
2. 2. 2.子树权值 % 3 = 1 \%3=1 %3=1,把当前节点权值修改为 1 1 1即可
3. 3. 3.子树权值 % 3 = 2 \%3=2 %3=2,把当前节点和它的一个白色节点的孩子都修改为 1 1 1
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
(我说比赛的时候真是脑子抽抽了吧,什么都写不出来)
#include <bits/stdc++.h>
#define int long long
#define YES "YES"
#define NO "NO"
#define all(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef __uint128_t ulll;
typedef pair<int, int> pii;
const double eps = 1e-9;
const int N = 2e6 + 10;
const int INF = 1e16;
const int mod = 1e9 + 7;
mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int n, flag;
string s;
vector<int> G[N];
int a[N];
void dfs1(int now)
{
int cnt = 0;
for(auto u : G[now])
{
if(s[u] == 'W')
cnt++;
dfs1(u);
}
if(cnt == 0 && s[now] == 'R')
flag = 1;
}
int dfs2(int now)
{
a[now] = 2;
int tot = a[now];
for(auto u : G[now])
{
tot += dfs2(u);
}
if(s[now] == 'R')
{
if(tot % 3 == 1)
a[now] = 1;
else if(tot % 3 == 2)
{
a[now] = 1;
for(auto u : G[now])
{
if(s[u] == 'W')
{
a[u] = 1;
break;
}
}
}
tot = 3;
}
return tot;
}
void solve()
{
cin >> n;
cin >> s;
s = " " + s;
for(int i = 2;i <= n;i++)
{
int u;
cin >> u;
G[u].push_back(i);
}
dfs1(1);
if(flag)
{
cout << "-1" << '\n';
return;
}
dfs2(1);
for(int i = 1;i <= n;i++)
cout << a[i];
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}