补一下,忘写了(
D. Scammy Game Ad
题目:
思路:
这道题其实是一道贪心的题目,我们先来分析一下几种情况
①. +x | +x
对于都是相加的情况,其实我们无论要不要调换轨道都是一样的
②.*x | *x
对于乘以相同的数字,其实我们无论要不要调换轨道也都是一样的
③.*x | +y
对于一个乘,一个加的选择,我们肯定是要乘的门上多走点人,这样才能利益最大化,因为加门无论多少人都是加x人,所以只要有一人即可
④.*x | *(x+1)
对于乘以不同的数字,我们肯定要更多人往乘以多的门上走,这样才能利益最大化
单独情况我们分析完毕,那我们结合整体情况分析
首先,如果我们遇到一个门,我们是没法在门前进行分配的,因为每次分配只能在通过门之后分配,所以我们直接往后考虑
假设对于第一个门,我们无法通过分配最大化利益,那我们只能从他后面的门考虑,从上诉情况中我们可以直到,只有当情况③和④时进行分配才是最好的
所以我们向后枚举,如果遇到*x | +y的情况,那我们当前分配就要往乘上,如果遇到*x | *(x+1)情况,那我们就往乘的数大的门上走
代码:
#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define ll long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
char cL[35],cR[35];
int nL[35], nR[35];
void solve()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> cL[i] >> nL[i] >> cR[i] >> nR[i];
}
ll l = 1, r = 1;
for (int i = 0; i < n; i++)
{
ll add = 0;
bool goleft = true;
for (int j = i+1; j < n; j++)
{
if (cL[j] != cR[j])
{
if (cR[j] == 'x')
goleft = false;
break;
}
else if (cL[j] == 'x' && nL[j] != nR[j])
{
if (nR[j] == 3)
goleft = false;
break;
}
}
if (cL[i] == '+')
add += nL[i];
else
add += l * (nL[i] - 1);
if (cR[i] == '+')
add += nR[i];
else
add += r * (nR[i] - 1);
if (goleft)
l += add;
else
r += add;
}
cout << l + r << endl;
}
int main()
{
// cin.tie(0)->sync_with_stdio(false);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. XOR and Triangle
题目:
思路:
题目要求我们找出一个y,使得x,y,x^y能构成一个三角形,那么显然我们只需要考虑两小边是否大于第三边就行了,同时y是小于x的,所以y一定不是最大边,那么我们就考虑两种情况(设x^y=z)
①.x是最大边
假设有:
x:11100010
那么先不考虑最高位要不要取1,我们就假设是0,这样方便我们后面讨论,防止y会大于x
所以y应该是这样的0......
那么假如我们遇到了1,那么我们就考虑要选什么,如果我们选了0,那么z就是1,如果选了1,那么z就是0,可以看到无论选什么,y+z都是等于x的,所以无影响
那么假如我们遇到了0,这是就要选1了,为什么?因为如果我们选0,那么z也是0,最后相加还是0,这显然不利于我们y+z>x,所以肯定要选1,这样z也是1了
②.x^y是最大边
同上思考,但是这里遇到1和遇到0就反过来了,这里是遇到1要选1,遇到0无所谓
那我们结合两种情况,由于我们每次都不知道到底谁是最大边,那我们肯定要尽量都往好的上选,所以我们对于y,无论x位置上是啥,我们都选1就行了,特别的,首位不能选1,必须选0
那么回到y最高位要不要选0,其实如果y选了1,那么就相当于y=x^z了,因为这时z的首位是0,而y和z其实是一个因果关系,因此相当于反过来考虑了
所以对于y,我们可以考虑构造一个01111...的数字,这样无论是x是最大边还是z是最大边我们都能满足,如果此时都不能满足,说明肯定没有解了
(以上为个人的见解)
代码:
#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define ll long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
void solve()
{
int x;
cin >> x;
int w = 0;
for (int i = 31; i >= 0; i--)
{
if ((x >> i) & 1)
{
w = i;
break;
}
}
int y = (1 << w) - 1;
int z = x ^ y;
if (y < x && x+y > z && x+z > y && y+z > x)
{
cout << y << endl;
return;
}
cout << -1 << endl;
}
int main()
{
// cin.tie(0)->sync_with_stdio(false);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}