A题:
思路:
模拟题
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 1e5 + 10, M = 1e3;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
int x;
cin >> x;
if (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;
}
B题:
思路:
代码:
C题:
思路:
贪心,越大的背包应该放在越中间的位置。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 1e5 + 10, mod = 1e9 + 7;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
//code here
int n;
cin >> n;
vector<LL>a(n);
vector<LL>b(n);
infor(i, 0, n - 1)a[i] = i + 1;
sort(a.begin(), a.end());
int l = 0, r = n - 1, cnt = 0;
bool flag = true;
while(l < r)
{
if (flag)
{
b[l++] = a[cnt++];
flag = !flag;
}
else
{
b[r--] = a[cnt++];
flag = !flag;
}
}
b[l] = a[cnt];
a = b;
infor(i, 1, n - 1)
{
for(int j = 0; j < b.size(); j ++)
{
b[j] = (b[j] + b[j + 1]) % mod;
}
b.pop_back();
}
cout << b[0] << '\n';
for(auto i : a)cout << i << " ";
return 0;
}
D题:
思路:
最初思想:暴力枚举每一个位置,然后求贡献总和,找到修改后贡献总和最小的那个位置。
关键在于如何O(1)的求出每个位置的贡献。f[i]表示i的前面,b[i]表示i的后面
每个位置的贡献 = f[i]空集 * b[i]”udu + f[i]”u” * b[i]”du” + f[i]”ud” * b[i]”u” + f[i]”udu”*b[i]空集。
使用dp讲我们需要的数组dp出来即可。要理解状态转移方程和需要注意空集的选法总是1.
还有出题人非常恶心的卡了LL。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 2e5 + 10, mod = 1e9 + 7;
string s;
LL dpf[N][4], dpb[N][4];
string e = "udu";
void work(LL dp[][4], int n)//dp[a][b] 表示从前i个中,b字串有多少个
{
dp[0][0] = 1;
infor(i, 1, n)
{
//空集总是有一种选法的
dp[i][0] = 1;
infor(j, 1, 3)
{
dp[i][j] = dp[i - 1][j];
if (s[i - 1] == e[j - 1])dp[i][j] += dp[i - 1][j - 1];
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
//code here
cin >> s;
int n = s.size();
work(dpf, n);
reverse(s.begin(), s.end());
work(dpb, n);
reverse(s.begin(), s.end());
LL ans = 1e18;
int res = -1;
infor(i, 1, n)
{
LL temp = 0;
infor(j, 0, 3)
{
temp += dpf[i - 1][j]*dpb[n - i][3 - j];
}
if (temp < ans)
{
ans = temp;
res = i;
}
}
s[res - 1] = 'z';
cout << s << '\n';
return 0;
}
E题:
思路:
代码:
F题:
思路:
按照题中说的照做,每次去除最大的值操作m次,注意一个数最大不超过3次就会收敛了。
使用小根堆,
维护询问的答案的数组ans[i],的值为询问为k时,答案是多少。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 1e5 + 10, mod = 1e9 + 7;
int a[2*N];
int book[6*N];
int func(int x)
{
int res = 0;
defor(i, 31, 0)
{
res += ((x >> i) & 1);
}
return res;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
//code here
int n, q;
cin >> n >> q;
infor(i, 0, n - 1)cin >> a[i];
priority_queue<int, vector<int>, less<int>>heap;
infor(i, 0, n-1)heap.push(a[i]);
// --- 不知道为啥这样写会段错
// int onenum = 0;
// infor(i, 1, 3*n)
// {
// auto tem = heap.top();
// heap.pop();
// tem = func(tem);
// heap.push(tem);
// book[i] = heap.top();
// }
// ---
int cnt = 0;
while(!heap.empty())
{
int top = heap.top();
heap.pop();
if (top == 1)continue;
heap.push(func(top));
book[cnt++] = top;
}
while(q--)
{
int k;
cin >> k;
if (k >= cnt)
{
cout << 1 << '\n';
continue;
}
cout << book[k] << '\n';
}
return 0;
}
G题:
思路:
取出k对数,取每一对的时候取法只有两种:
1、取出最小的两个数相乘(因为可能有负数)
2、取出最大的两个数相乘(正整数情况)
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 1e5 + 10, mod = 1e9 + 7;
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
//code here
int n, k;
cin >> n >> k;
vector<LL>a(n);
infor(i, 0, n - 1)
{
cin >> a[i];
}
sort(a.begin(),a.end());
int l = 0, r = a.size() - 1;
LL res = 0ll;
infor(i, 0, k - 1)
{
LL ans1 = a[l] * a[l + 1];
LL ans2 = a[r] * a[r - 1];
if (ans1 >= ans2)
{
l += 2;
res += ans1;
}
else
{
r -= 2;
res += ans2;
}
}
cout << res << '\n';
return 0;
}
H题:
思路:
根据题目模拟,算区间占比即可
代码:
#include <iostream>
#include <algorithm>
#include <vector>
#define infor(i, a, b) for (int i = a; i <= b; i++)
#define defor(i, a, b) for (int i = a; i >= b; i--)
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int N = 1e5 + 10, M = 1e3;
int main()
{
// std::ios::sync_with_stdio(false);
// cin.tie(0);
int x, l, r;
scanf("%d", &x);
scanf("%d%d", &l, &r);
if (x <= l)printf("%d", 0);
else if (l < x && x <= r)
{
printf("%.9f", ( (x - l)*1.0)/((r - l + 1)*1.0) );
}
else printf("%d",1);
return 0;
}