AtCoder Beginner Contest 389 Solution
A - 9x9 (abc389 A)
题目大意
给定形如9x9的三位输入,把这个式子结果算出来
解题思路
scanf
代码
void solve()
{
int a, b;
scanf("%dx%d", &a, &b);
cout << a * b;
}
B - tcaF (abc389 B)
题目大意
给定X,保证X=n!,求n
解题思路
循环即可
代码
#define ll long long
void solve()
{
ll n;
cin >> n;
ll x = 1;
int i = 1;
while (x < n) {
if (x * i == n) cout << i;
x *= i;
i++;
}
}
C - Snake Queue (abc389 C)
题目大意
有好多条蛇排队,一开始队列是空的,一共有Q次查询。
第一种给定l,将长度为l的蛇添加到队列末尾,如果队列是空的,那么蛇头位置是0,否则是前面所有蛇长度之和。
第二种表示最前面的蛇离开队列,剩下所有的蛇头位置会减去这条蛇的长度。
第三种给定k,问此时队列从前向后第k条蛇的蛇头位置。
解题思路
模拟一下,想咋做都行,我的方法是开一个vector记录当前每条蛇的蛇头位置,如果有蛇入队,就把新的蛇长加上加进队列,并且我在一开始压入一个0。
具体效果:比如三条蛇长度为2,3,4入队,那么v:0,2,5,9
第一条蛇蛇头位置为0,第二条为2,第三条为5,最后那个9其实暂时不表示蛇头位置,只是蛇长总和,有新蛇进来他就自动变成新蛇的蛇头位置了。
弹出的话就在vector里记录一个d表示有几条蛇出去了就行,查询第k条,那么其实查询的是第k+d条,然后减去前d条的蛇长即可。
代码
#define ll long long
#define pb push_back
void solve()
{
int T;
cin >> T;
vector<ll> v;
v.pb(0);
int d = 0;
while (T--) {
int c, x;
cin >> c;
if (c == 1) {
cin >> x;
v.pb(*v.rbegin() + x);
}
else if (c == 2) {
d++;
}
else {
cin >> x;
cout << v[x + d - 1] - v[d] << endl;
}
}
}
D - Squares in Circle (abc389 D)
题目大意
有一个由1*1方格组成的无限大的网格,问以一个方格的中心作为圆心,R作为半径的圆中,完整包括了多少个方格。
解题思路
数据范围1e6,做法也很多,可以利用单调性,我是枚举高度然后勾股定理。
代码
void solve()
{
double n;
cin >> n;
ll ans = 0;
for (double i = 1.5;i <= n;i += 1.0) {
double h = i;
double c = sqrt(1.0 * n * n - h * h);
if (c > 0.5) ans += floor(c - 0.5) * 2 + 1;
}
ans *= 2;
double h = 0.5;
double c = sqrt(1.0 * n * n - h * h) * 2.0;
ans += floor(c);
cout << ans << endl;
}
E - Square Price (abc389 E)
题目大意
有无限多的物品,第i种物品的价格为pi,如果第i种物品买了k个,那么需要花费$k^2p_i$的钱
现在有M块,问最多买多少件物品
解题思路
对于$k^2p_i$的条件我们可以拆开看,第一件是pi元,那么第二件就是3pi元,第三件是5pi,因为项数为k的1,3,5,7等差数列之和就是k^2,我们可以看做每件商品买了之后会涨价。
那么我们的策略肯定是哪个便宜买哪个,从最便宜的开始买起,我们需要知道买到一件多少钱的商品时总价要超过M了,那么这是一个很显然的二分,二分这件最贵的商品的价格,然后我们要算总价,总价我们可以根据每一种商品的单价推出这种商品买了多少个,从而可以算出总价,总价要小于M。
二分出的价格为mid,某个商品价格为pi,如果这个商品买了x件,那么有(x*2-1)pi<=mid,也就可以除一下算出x,那么总价就是pix^2。
那么这里还有一个问题,有可能很多件商品的最贵的价格相同,比如3种商品价格分别为3,5,7。那么对于105,他们三都有可能价格为105,105也就可以买1~3件,那么我们算出不买这件最贵商品剩下多少钱,最后再除一下加上这种最贵商品即可。
代码
#include<bits/stdc++.h>
using namespace std;
int n,p[200005];long long m;
bool check(long long mid){
long long sum=0;
for(int i=1;i<=n;i++){
long long tmp=(mid+p[i])/(2ll*p[i]);
if(tmp>INT_MAX)return false;
if(tmp*tmp>(long long)INT_MAX*INT_MAX/p[i])return false;
sum+=tmp*tmp*p[i];
if(sum>=m)return false;
}
return true;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>p[i];
long long l=1,r=1e18;
while(l<=r){
long long mid=l+r>>1;
if(check(mid))l=mid+1;
else r=mid-1;
}
long long ans=0;
for(int i=1;i<=n;i++){
long long tmp=((l-1)+p[i])/(2ll*p[i]);
ans+=tmp;
m-=tmp*tmp*p[i];
}
cout<<ans+m/l<<endl;
}