A
题意:
给定一个一位数乘一位数的式子,求其结果
大致思路:
将一个字符和最后一个字符转为int类型相乘。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
void solve()
{
string s;
cin >> s;
int a = s[0] - '0';
int b = s[2] - '0';
cout << a * b;
}
int main()
{
//IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}
B
题意:
给定X,并且X是某个数的阶乘,求出那个数
大致思路:
暴力枚举并判断是否等于X即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
void solve()
{
ll x;
cin >> x;
for (int i = 1; i <= 30; i++)
{
ll sum = 1;
for (ll j = 1; j <= i; j++)
{
sum *= j;
}
if (sum == x)
{
cout << i;
return;
}
}
}
int main()
{
//IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}
C
题意:
维护一条蛇队列,有添加蛇,删除蛇,询问某条蛇的位置三种操作
大致思路:
用前缀和维护蛇队列,这样能快速求出蛇的位置
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[300007], b[300007], cnt = 1, k;
void solve()
{
ll n, x, y;
cin >> n;
while (n--)
{
cin >> x;
if (x == 1)
{
cin >> y;
a[cnt] = y;
b[cnt] = a[cnt] + b[cnt - 1];
cnt++;
}
else if (x == 3)
{
cin >> y;
cout << b[y + k - 1] - b[k] << '\n';
}
else k++;
}
}
int main()
{
IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}
D
题意:
以其中一个正方形的中心为圆心,画一个半径为 R 的圆,求有多少个正方形完全包含在圆内
大致思路:
以圆心为原点,先算出坐标轴上包含几个正方形,再算出其他四个象限包含几个正方形
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n, m, a[200007];
void solve()
{
ll r;
cin >> r;
ll ans = 4ll * (floor)(r - 0.5);
for (int i = 1; i < r; i++)
{
ll y = (sqrt(r * r - (i + 0.5) * (i + 0.5)) - 0.5);
ans =ans+ y * 4;
}
cout << ans+1;
}
int main()
{
IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}
E
题意:
有n种商品,m元钱,购买k件第j种商品的价格是k*k*a[j],求最多买几件商品。
大致思路:
先考虑暴力的思路:一直挑最便宜的买,买到最后一定是件数最多的情况。
观察到还没购买的最便宜的商品的价格随着件数的上升而上升。图像大致如下:
(ab段是由于可能出现多个价格相同的商品)
因为可以通过下一件商品的最低价格(或者是已购买商品的最高价格)求出需要花费的总价,来判断该件数y是否合法。
所以可以对已购买商品的最高价格进行二分,更快求出答案。
同时因为答案可能出现在ab段之间的位置,而二分也无法到达该位置,可以在mid指针指向b-1(ab对于x轴的坐标 - 1)时,用剩下的钱尽可能地去购买等于(mid+1)价格的产品去到达ab之间的位置。(看了暴力代码就非常好理解了)
暴力代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n, m, a[200007], as, ans, flag[200007];
priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>q;
ll ff(ll x)
{
ll y = x - 1;
return x * x - y * y;
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
q.emplace(a[i],i);
}
while (!q.empty())
{
ll t1 = q.top().first;
ll t2 = q.top().second;
q.pop();
if (t1 > m)break;
ans++;
flag[t2]++;
m -= t1;
ll k = flag[t2]+1;
k = ff(k);
q.emplace(k * a[t2], t2);
}
cout << ans << '\n';
}
int main()
{
IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}
正解:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int __int128
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n, m, a[200007], as, ans, d[200007];
bool check(int mid)
{
int sum = 0;
as = 0;
for (int i = 1; i <= n; i++)
{
int k = mid / a[i] + 1 >> 1;
sum += k * k * a[i];
if (sum > m)return 0;
as += k;
d[i] = k;
}
for (int i = 1; i <= n; i++)
{
int tmp = ((d[i] + 1) * (d[i] + 1) - d[i] * d[i]) * a[i];
if (tmp != mid + 1||tmp+sum>m)continue;
sum += tmp;
as++;
}
return 1;
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)cin >> a[i];
sort(a + 1, a + 1 + n);
int l = 0, r = m;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid))
{
l = mid;
}
else
{
r = mid - 1;
}
ans = max(as, ans);
}
cout << ans;
}
signed main()
{
IOS();
int T;
//cin >> T;
T = 1;
while (T--)
{
solve();
}
}