#847 div3
B:
题目:
现在有 n 个 六面骰子,都随机掷出,结果构成一个序列,给出这个序列所有元素的和, 还有去掉最高元素的和。
问你可能的序列是什么
思路:
可以得到最大值是多少,其他都至少为1,不超过最大值即可
代码
void solved()
{
int n, m, s;
cin >> n >> m >> s;
int mxx = m - s;
ans[1] = mxx;
s -= n - 1;
for(int i = 2; i <= n; i++) ans[i] = 1;
for(int i = 2; i <= n; i++)
{
if(s - (mxx - 1) >= 0)
{
s -= mxx - 1;
ans[i] += mxx - 1;
}else
{
ans[i] += s;
break;
}
}
for(int i = 1; i <= n; i++) cout << ans[i] << " ";
cout << endl;
}
C:
题目:
原本存在一个长度为 n 的序列,现在给出 n 个 序列, 分别对应去掉下标为 1 - n ,所剩下的序列。
思路:
观察规律,开头和结尾都是出现三次的数字,然后另一个数字就是下一个的数字。
代码
void solved()
{
memset(cnt, 0, sizeof cnt);
memset(w, 0, sizeof w);
cin >> n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n - 1; j++)
{
int x;
cin >> x;
cnt[j][x]++;
if(!w[j][0]) w[j][0] = x;
else
{
if(x != w[j][0]) w[j][1] = x;
}
}
}
int last = 0;
for(int i = n - 1; i >= 1; i--)
{
if(i == n - 1)
{
if(cnt[i][w[i][0]] > cnt[i][w[i][1]]) ans[i + 1] = w[i][0], last = w[i][1];
else ans[i + 1] = w[i][1], last = w[i][0];
continue;
}
if(i == 1)
{
if(cnt[i][w[i][0]] > cnt[i][w[i][1]]) ans[i] = w[i][0], ans[i + 1] = w[i][1];
else ans[i] = w[i][1], ans[i + 1] = w[i][0];
continue;
}
if(w[i][0] == last)
{
ans[i + 1] = last;
last = w[i][1];
}else
{
ans[i + 1] = last;
last = w[i][0];
}
}
for(int i = 1; i <= n; i++) cout << ans[i] << " ";
cout << endl;
}
D:
题目:
现在存在 n 个数,让你分成最小个数的组,使得组内都是连续的数字。
思路:
首先统计一下每个数字出现的个数。然后把所有数字排序。
排序后,可以看成几个块,块内都是连续的。
对于块内:
因为组内必须是连续的,所以因为块内个数是不同的,所以块内消耗后可能又导致不连续。
如果相邻两个数字的个数存在逆序,那么后面的数字因为个数小,会被先用完。这样中间连续会被断开。
例如连续的一组内个数分别为, 2 1 3 4, 存在逆序 2 1,1用完之后, 前面的 与 后面无法共组。
那么就要单独为一组,那么他们的差就是单独共组的,直到遇到不连续的,到下一个块了。
还要加上数字中最大个数
代码
void solved()
{
map<int, int> hs;
vector<int> a;
cin >> n;
for(int i = 1; i <= n; i++)
{
int x;
cin >> x;
if(!hs[x])
{
a.push_back(x);
}
hs[x]++;
}
sort(a.begin(), a.end());
int mxx = hs[a[0]];
int ans = 0;
int len = a.size();
for(int i = 1; i < len; i++)
{
int x = a[i];
if(a[i] == a[i - 1] + 1)
{
if(hs[a[i - 1]] > hs[a[i]])
{
ans += (hs[a[i - 1]] - hs[a[i]]);
}
mxx = (hs[a[i]]);
}else
{
ans += mxx;
mxx = hs[a[i]];
}
mxx = max(mxx, hs[x]);
}
ans += mxx;
cout << ans << endl;
}
E:
题目:略
思路:
对于当前给出的 x,a + b >> 为 x,那么意味着当存在一位 x 上为 1,下一位 a 和 b 对应位都应该为 1,这样可以进位到当前位置。
因为 a ^ b 为 x,
存在两种情况,
当位上位 1: 那么填 0 1 或者 1 0, 对于相加来说都一样,都归为 a 为 1, b 为 0
如果位上为 0, 那么填 11 或者 00。
参考上面,如果说当前位置为1, 需要下一位都是 11,但是如果下一位为 1,就矛盾了,输出 -1。
如果说当前位置为 0,就跳过,因为前一位已经决定了。
对于最后一位,如果是 1 因为不存在下一位,肯定不合法。
代码
void solved()
{
int x;
cin >> x;
int a = 0, b = 0;
if(x & 1)
{
cout << -1 << endl;
return;
}
for(int i = 1; i <= 30; i++)
{
if(x >> i & 1)
{
if(x >> (i - 1) & 1)
{
cout << -1 <<endl;
return;
}
}
if(x >> i & 1)
{
a += 1 << i;
a += 1 << (i - 1);
b += 1 << (i - 1);
}
}
cout << a << " " << b << endl;
}