牛客编程巅峰赛S1第3场 - 青铜&白银
A-[位数求和]
思路:
直接按照枚举([10^n,10^{n+1}-1])种的每个数,$O(log_{10}(x))判断每位上的数字之和为m即可。
代码:
class Solution {
public:
/**
* 返回这样的数之和
* @param n int整型 数的长度
* @param m int整型 各个为之和
* @return long长整型
*/
long long sum(int n, int m) {
// write code here
int base = 1;
for (int i = 1; i <= n - 1; ++i)
{
base *= 10;
}
int up = base * 10 - 1;
long long ans = 0;
for (int i = base; i <= up; ++i)
{
int num = i;
int cnt = 0;
while (num > 0)
{
cnt += num % 10;
num /= 10;
}
if (cnt == m)
{
ans += i;
}
}
return ans;
}
};
B-不可思议
思路:
仔细观察生成的树的随机代码:
seed4 = (seed1 + seed2) % 998244353 * seed3 % 998244353;
u[i] = i + 1;
v[i] = (seed4 % i) + 1;
每一个边都是一个新节点和之前已经出现的节点连边。
这样生成的树高度的期望值是(O(log_2(n))),所以先预处理每一个节点的父节点后,
对于每一个询问可以直接暴力求即可。
代码:
class Solution {
public:
/**
*
* @param n int整型
* @param seed1 long长整型
* @param seed2 long长整型
* @param seed3 long长整型
* @param x int整型
* @return long长整型
*/
int u[100010], v[100010];
std::vector<int> e[100010];
void get_tree(long long seed1 , long long seed2, long long seed3, int n)
{
long long seed4;
for (int i = 1; i <= n - 1; ++i)
{
seed4 = (seed1 + seed2) % 998244353 * seed3 % 998244353;
u[i] = i + 1;
v[i] = (seed4 % i) + 1;
seed3 = seed2;
seed2 = seed1;
seed1 = seed4;
}
}
int far[100010];
void dfs(int x, int pre)
{
far[x] = pre;
for (auto &y : e[x])
{
if (y != pre)
{
dfs(y, x);
}
}
}
int ans(int x, int y)
{
int res = 0;
while (1)
{
res += ((y + 2 * x) ^ (y + x));
if (x == 1)
{
break;
} else
{
x = far[x];
}
}
return res;
}
long long work(int n, long long seed1, long long seed2, long long seed3, int x) {
// write code here
get_tree(seed1, seed2, seed3, n);
for (int i = 1; i < n; ++i)
{
e[v[i]].push_back(u[i]);
e[u[i]].push_back(v[i]);
}
dfs(1, 0);
int lastans = 0;
int ret = 0;
int y = 0;
int z;
for (int i = 1; i <= n; ++i)
{
z = ans(x, y);
ret = (ret + z) % 998244353;
lastans = z;
x = ((x + lastans)^ret) % n + 1;
y = lastans;
}
return ret;
}
};
C-牛牛晾衣服
思路:
二分(mid)代表要多少时间可以把衣服全烘干,显然具有单调性((mid)可以烘干的话,(mid+1)一定可以。)
然后对于每一个衣服(a_i),找到最小的(x)使其(a_i-x*k-(mid-x)<=0),然后如果可以找到且(xin[0,mid]),以及(mathit x)的总和(sumle mid)。
代码:
class Solution {
public:
int C(int x, int y)
{
return (x + y - 1) / y;
}
bool check(int mid, vector<int>& a, int k)
{
int n = a.size();
int cnt = 0;
if (mid >= a[0])
return 1;
for (int i = 0; i < n; ++i)
{
if (mid * k < a[i])
return 0;
int x = C(max(a[i] - mid, 0), k - 1);
if (x < 0 || x > mid)
{
return 0;
}
cnt += x;
}
return cnt <= mid;
}
int solve(int n, vector<int>& a, int k) {
// write code here
sort(a.begin(), a.end(), greater<int>());
int l = 1;
int r = 1000000000;
int mid;
int ans ;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid, a, k))
{
ans = mid;
r = mid - 1;
} else
{
l = mid + 1;
}
}
return ans;
}
};