模拟
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int x;
cin >> x;
if (x >= 1 && x <= 7) {
cout << "very easy\n";
} else if (x <= 233) {
cout << "easy\n";
} else if (x <= 10032) {
cout << "medium\n";
} else if (x <= 114514) {
cout << "hard\n";
} else if (x <= 1919810) {
cout << "very hard\n";
} else {
cout << "can not imagine\n";
}
return 0;
}
首先预处理出每个数都是谁的倍数,时间复杂度nlogn,然后从1~n,对所有a[i]整除的数+1,相当于前缀和,最后查询的时候只需要算出 能被整除的-x及以前能被整除的 即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
vector<int> G[200010];
int sum[200010], ans[400010];
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
for (int i = 1; i <= 200000; i++) {
for (int j = i; j <= 200000; j += i) {
G[j].push_back(i);
}
}
int n, q;
cin >> n >> q;
vector<int> a;
a.push_back(0x3f3f3f3f);
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
a.push_back(x);
for (auto it : G[x]) {
sum[it]++;
}
ans[i] = sum[x];
}
while (q--) {
int op, x;
cin >> op >> x;
if (op == 1) {
n++;
a.push_back(x);
for (auto it : G[x]) {
sum[it]++;
}
ans[n] = sum[x];
} else {
cout << sum[a[x]] - ans[x] << '\n';
}
}
return 0;
}
计算每个数对答案的贡献,可知是个杨辉三角,即越是中间的数贡献越大,所以把大的数优先放在中间,小的数放两边,暴力计算即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
const int mod = 1e9 + 7;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
deque<int> q;
for (int i = n; i >= 1; i--) {
if (i % 2 == 0) {
q.push_front(i);
} else {
q.push_back(i);
}
}
vector<int> a, ans;
while (!q.empty()) {
int x = q.front();
q.pop_front();
a.push_back(x);
}
ans = a;
for (int i = 0; i < n - 1; i++) {
vector<int> b;
int len = a.size();
for (int j = 0; j < len - 1; j++) {
b.push_back((a[j] + a[j + 1]) % mod);
}
a = b;
}
cout << a[0] << '\n';
for (int i = 0; i < n; i++) {
cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}
首先容易想到的是如果要删掉u的话一定是从第一个u或者最后一个u当中选择一个更好的删除,因为当这个u后面出现一个d的时候,d后面再遇到u的话每个u的贡献就多了1,因为可以选择多个d组成udu,如果选两个d中间的u,u左边的贡献从1开始,右边也是从1开始,明显小于两端的u,因此能够求出两端的一个u分别能产生多少贡献,然后如果要删掉d的话,需要计算一个d能影响多少,即d左边u的个数*d右边u的个数,然后找出三者贡献最大的,修改掉即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s = "";
cin >> s;
int len = s.size();
int sum = 0;
vector<int> x, y;
for (int i = 0; i < len; i++) {
if (s[i] == 'u') {
sum++;
}
if (s[i] == 'd') {
x.push_back(sum);
}
}
sum = 0;
for (int i = len - 1; i >= 0; i--) {
if (s[i] == 'u') {
sum++;
}
if (s[i] == 'd') {
y.push_back(sum);
}
}
int pre = 0, end = len - 1, ans1 = 0, ans2 = 0, cnt = 0;
while (s[pre] != 'u' && pre < len) {
pre++;
}
while (s[end] != 'u' && end >= 0) {
end--;
}
for (int i = pre; i < len; i++) {
if (s[i] == 'd') {
cnt++;
}
if (s[i] == 'u') {
ans1 += cnt;
}
}
cnt = 0;
for (int i = end; i >= 0; i--) {
if (s[i] == 'd') {
cnt++;
}
if (s[i] == 'u') {
ans2 += cnt;
}
}
int l = 0, r = x.size() - 1;
int idx = 0, ans3 = 0;
for (int i = 0; i < len; i++) {
if (s[i] == 'd') {
int res = x[l] * y[r];
if (res > ans3) {
idx = i;
ans3 = res;
}
l++;
r--;
}
}
if (ans1 >= ans3 && ans1 >= ans2) {
s[pre] = 'z';
cout << s << '\n';
} else if (ans2 >= ans1 && ans2 >= ans3) {
s[end] = 'z';
cout << s << '\n';
} else {
s[idx] = 'z';
cout << s << '\n';
}
return 0;
}
不难想到的是,1和所有数互质,所以如果是gcd(i,j),那么一定和1连接最优,边权为1,可知对于n个数素数的密度大概是n/ln(n),所以当只能和1连lcm(i,j)时,考虑其和[i+k+1,n]之间的连gcd(i,j)边,因为素数密度不大,所以暴力找到一个gcd(i,j)==1的数即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
function<LL(LL, LL)> gcd = [&](LL a, LL b) {
return b == 0 ? a : gcd(b, a % b);
};
int ans = 0;
for (int i = 2; i <= n; i++) {
if (i - 1 <= k) {
int p = i;
for (int j = i + k + 1; j <= n; j++) {
p = min(p, gcd(i, j));
if (p == 1) {
break;
}
}
ans += p;
} else {
ans++;
}
}
cout << ans << '\n';
return 0;
}
根据题意可知,经过有限次且次数并不大的操作即可把一个数变成1,所以每次选最大的数进行操作,提前记录每次操作后剩下的最大值是多少即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
int ans[1000010];
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
priority_queue<int, vector<int>, less<int>> qb, qc;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
qb.push(a[i]);
}
int sum = 0;
qc = qb;
ans[sum] = qc.top();
while (qc.top() != 1) {
int now = qc.top();
qc.pop();
now = __builtin_popcount(now);
qc.push(now);
sum++;
ans[sum] = qc.top();
}
while (q--) {
int k;
cin >> k;
if (k >= sum) {
cout << "1\n";
continue;
}
cout << ans[k] << '\n';
}
return 0;
}
为了尽可能地大,只能小的负数与小的负数相乘,大的正数与大的正数相乘,得到的结果相加才越大,因此每次选择小的负数与小的负数相乘和大的正数与大的正数相乘中最大的,如果正数小于2或负数小于2,能乘0优先乘0,否则一定会出现负数
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
LL ans = 0, cnt = 0;
priority_queue<int, vector<int>, less<int>> qa;
priority_queue<int, vector<int>, greater<int>> qb;
for (int i = 0; i < n; i++) {
int p;
cin >> p;
if (p > 0) {
qa.push(p);
} else if (p == 0) {
cnt++;
} else {
qb.push(p);
}
}
while (k) {
int len1 = qa.size(), len2 = qb.size();
int x, y, xx, yy;
if (len1 >= 2 && len2 >= 2) {
x = qa.top();
qa.pop();
y = qa.top();
qa.pop();
xx = qb.top();
qb.pop();
yy = qb.top();
qb.pop();
if (x * y > xx * yy) {
ans += x * y;
qb.push(xx);
qb.push(yy);
} else {
ans += xx * yy;
qa.push(x);
qa.push(y);
}
} else if (len1 >= 2) {
x = qa.top();
qa.pop();
y = qa.top();
qa.pop();
ans += x * y;
} else if (len2 >= 2) {
xx = qb.top();
qb.pop();
yy = qb.top();
qb.pop();
ans += xx * yy;
} else if (cnt > 0) {
if (len1 > 0) {
qa.pop();
cnt--;
} else if (len2 > 0) {
qb.pop();
cnt--;
} else {
cnt -= 2;
}
} else {
x = qa.top();
qa.pop();
xx = qb.top();
qb.pop();
ans += x * xx;
}
k--;
}
cout << ans << '\n';
return 0;
}
找出脆皮还有的区间除以总的区间长度即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int x, l, r;
cin >> x >> l >> r;
if (x > r) {
cout << "1.000000000\n";
} else if (x < l) {
cout << "0.000000000\n";
} else {
int t = r - x + 1, q = x - l;
int sum = r - l + 1;
double ans = 1.0 * q / sum;
cout << fixed << setprecision(10) << ans << '\n';
}
return 0;
}
可知,如果前往沙城最近的路的长度等于所有的边数,那么第一条路必须走边权的长度,其他路边权全部变成1,也就是走过的路全部毁灭,下一条路边权变成1,如果前往沙城最近的路的长度小于所有的边数,那么前往沙城所有路的边权都是1,选择其他不是前往沙城的路毁灭,要走的路边权变成1
AC代码:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<vector<pair<int, int>>> G(n + 1);
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
G[u].push_back(make_pair(v, w));
G[v].push_back(make_pair(u, w));
}
vector<bool> vis(n + 1);
vector<int> dep(n + 1);
queue<int> q;
q.push(1);
vis[1] = true;
while (!q.empty()) {
int now = q.front();
q.pop();
for (auto v : G[now]) {
if (!vis[v.first]) {
dep[v.first] = dep[now] + 1;
q.push(v.first);
vis[v.first] = true;
}
}
}
if (m == dep[n]) {
cout << dep[n] - 1 + G[1][0].second << '\n';
} else {
cout << dep[n] << '\n';
}
return 0;
}