https://codeforc.es/contest/1355
A. Sequence with Digits
当数位中出现0时break
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
int main()
{
ll t, n, k;
scanf("%lld", &t);
while(t--)
{
scanf("%lld%lld", &n, &k);
for(ll i = 2; i <= k; ++i)
{
ll maxx = 0;
ll minn = 9;
ll tmp = n;
while(tmp)
{
maxx = max(maxx, tmp % 10);
minn = min(minn, tmp % 10);
tmp /= 10;
}
n += maxx * minn;
if(minn == 0)
{
break;
}
}
cout<<n<<'\n';
}
return 0;
}
B. Young Explorers
题意:
给出每个人的无经验值,一个队伍中的人数应 >= 该队中每个人的无经验值,问最多组多少队
思路:
相同无经验值的人尽量组在一起,剩下的人按无经验值从小到大排个序,cnt记录当前队的人数,当人数 == 当前人的无经验值时,正好组成一个队。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int main()
{
int t, n, v;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
map<int, int>mp;
map<int, int>::iterator it;
for(int i = 1; i <= n; ++i)
{
scanf("%d", &v);
mp[v]++;
}
int ans = 0;
vector<int>vec;
for(it = mp.begin(); it != mp.end(); ++it)
{
ans += it -> second / it -> first;
int cnt = it -> second % it -> first;
for(int i = 1; i <= cnt; ++i)
{
vec.push_back(it -> first);
}
}
int siz = vec.size();
int tmp = 0;
for(int i = 0; i < siz; ++i)
{
tmp++;
if(vec[i] == tmp)
{
ans++;
tmp = 0;
}
}
cout<<ans<<'\n';
vec.clear();
mp.clear();
}
return 0;
}
C. Count Triangles
题意:
给出a,b,c,d,令a <= x <= b <= y <= c <= z <= d,问由x,y,z组成的三角形有多少个
思路:
遍历最短边,即 i ~ [a,b],次短边的范围为[i + b,i + c],求该区间和最长边可取区间 [c,d] 的交集
分类讨论
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int main()
{
ll a, b, c, d;
while(~scanf("%lld%lld%lld%lld", &a, &b, &c, &d))
{
ll ans = 0;
for(ll i = a; i <= b; ++i)
{
if(i + b <= c && i + c <= d)
{
ans += i * (i + 1) / 2;
}
else if(i + b <= c && i + c > d)
{
ans += (d - c + 1) * (i + c - d - 1) + (d - c + 2) * (d - c + 1) / 2;
}
else if(i + b > c && i + b <= d && i + c <= d)
{
ans += (i - c + b) * (c - b + 1) + (1 + c - b) * (c - b) / 2;
}
else if(i + b > c && i + b <= d && i + c > d)
{
ans += (i + c - d) * (d - c + 1) + (d - i - b + 1) * (i + b - c) + (1 + d - i - b) * (d - i - b) / 2;
}
else if(i + b > d && i + c > d)
{
ans += (d - c + 1) * (c - b + 1);
}
}
cout << ans << '\n';
}
return 0;
}
D. Game With Array
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
int main()
{
int n, s, k;
while(~scanf("%d%d", &n, &s))
{
if(s < 2 * n)
{
cout<<"NO"<<'\n';
continue;
}
cout<<"YES"<<'\n';
for(int i = 1; i < n; ++i)
{
cout<<2<<' ';
}
cout<<s - 2 * n + 2<<'\n';
cout<<1<<'\n';
}
return 0;
}
E. Restorer Distance
题意:
有 n 个砖柱,给出每个砖柱的砖数,要求将所有砖柱处理成高度相同的砖柱 ,求总花费最小值
(1)放上一块砖花费A
(2)拿下一块砖花费R
(3)从一个砖柱上移动到另一个砖柱花费M
思路:
砖数和最终花费之间成二次函数关系,三分最终砖柱上有多少块砖,如果A + R > M时直接从一个地方移动到另一个地方
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 5;
ll n, u, d, m, h[N];
ll check(ll num)
{
ll up = 0, down = 0;
for(ll i = 1; i <= n; ++i)
{
if(h[i] > num)
{
down += h[i] - num;
}
else
{
up += num - h[i];
}
}
ll res = up * u + down * d;
if(u + d > m)
{
ll tmp = min(up, down);
res += m * tmp - (u + d) * tmp;
}
return res;
}
int main()
{
while(~scanf("%d%d%d%d", &n, &u, &d, &m))
{
for(ll i = 1; i <= n; ++i)
{
scanf("%lld", &h[i]);
}
ll l = 0, r = 1e9;
while(l + 10 < r)
{
ll m1 = l + (r - l) / 3;
ll m2 = r - (r - l) / 3;
ll tmp1 = check(m1);
ll tmp2 = check(m2);
if(tmp1 > tmp2)
{
l = m1;
}
else
{
r = m2;
}
}
ll res = inf;
for(ll i = l; i <= r; ++i)
{
res = min(res, check(i));
}
cout<<res<<'\n';
}
return 0;
}