B. Yet Another Coin Problem
真[https://www.bilibili.com/video/BV1o2421M7pV/]
不同硬币之间有倍数关系,使得一定数量后的小硬币可以被大硬币替代达到最优方案,而每个小硬币在最优下有可能的数量如下,进行枚举后找到最优方案。
1: 不多于2个 (3个1 会被 3 替代)
3: 不多于一个 (2个3 会被6替代)
6: 不多于4个 (5个6 会被 10或15替代)
10:不多于2个 (2个10 会被 15替代)
code:
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n, a, b, c, d, ans = 1e9 + 10, res;
cin >> n;
for (a = 0; a < 3; a++)
{
for (b = 0; b < 2; b++)
{
for (c = 0; c < 5; c++)
{
for (d = 0; d < 3; d++)
{
res = n - a - b * 3 - c * 6 - d * 10;
if (res < 0 || res % 15 != 0)
continue;
ans = min(ans, a + b + c + d + res / 15);
}
}
}
}
cout << ans << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
C. Find a Mine
选择询问的位置,特殊角为中间和四角,位于中间无法确定另一个mine的方向,利用(1, 1), (n, 1), (n, n), (1, n) 任意一点,可以确定mine1在某条线上。
在(1, 1)处,确定mine1位置, 选择对角点(n, n),确定mine2所在直线,再选择一角,与两线相交的两点任意查询, 即可确定其中一个矿井位置。
利用这一特性,一定可以找出其中一个mine。
直接遍历找交点非常烦 wa
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n, m, x, y, i, ii, x1, y1;
cin >> n >> m;
cout << "? 1 1" << endl;
cin >> x;
cout << "? " << n << " 1" << endl;
cin >> y;
if (x + 1 > n)
{
x = x + 1 - n + 1;
ii = n;
for (i = x; i <= n; i++, ii--)
{
if (abs(i - 1) + abs(ii - n) == y)
{
y1 = i;
x1 = ii;
break;
}
}
cout << "? " << x1 << " " << y1 << endl;
cin >> x;
if (x == 0)
{
cout << "! " << x1 << " " << y1 << endl;
return;
}
else
{
cout << "? " << n << " " << n << endl;
cin >> x;
}
}
else
{
x = x + 1;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
我们最后要确定点坐标的位置并做最后一次查询,不如直接设出(x1, y1), (x2, y2), 此时曼哈顿距离已经给出,列一元二次方程即可解得坐标位置。(其中有一个式子可能是无解,但另一正解一定是答案)
如下图:
式1:
x1-1+y1-1=a
n-x1+y1-1=b
式2:
n-x2+y2-1=b
n-x2+m-y2=c
解得 y1 = (a + b - n + 3) / 2, x1 = (n + 1 + a - b) / 2;
code
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n, m, a, b, c, x;
cin >> n >> m;
cout << "? 1 1" << endl;
cin >> a;
cout << "? " << n << " 1" << endl;
cin >> b;
cout << "? " << n << " " << m << endl;
cin >> c;
int y1 = (a + b - n + 3) / 2, x1 = (n + 1 + a - b) / 2;
int x2 = (2 * n + m - 1 - b - c) / 2, y2 = (m + 1 + b - c) / 2;
if (x1 < 1 || y1 < 1 || x1 > n || y1 > m)
cout << "! " << x2 << " " << y2 << endl;
else
{
cout << "? " << x1 << " " << y1 << endl;
cin >> x;
if(x == 0)
cout << "! " << x1 << " " << y1 << endl;
else
cout << "! " << x2 << " " << y2 << endl;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
2e63 约等于 1e19
2e64 约等于 1e20
D1. XOR Break — Solo Version
芝士栗子:
bitset
bitset<4> foo (string("1001")); 直接用
但注意 一个一个 be[0], be[1]是从个位开始赋值,cout << be 是直接输出
be.count() //求be中1的个数
be.size() //用来求位数
be.any() //检查be中是否有1 none是检查是否无 all检查是否全为1
首先观察到当为2的次方时,无可能
"1->0"时:只需令当前位为1 其余为0
"0->1"时:(1) 当最高位"0->1"前有"1-1"时,可以直接令y = m,一步得到所求 (包含于x^y<x中)
(2) 当前无时,如果最高位 "0->1"前有"1-0"两组时 令y = x ^ m, 再将y最高位1换为0,保证 y < x, 此时最高位异或结果为1 其他位已为所求, 这里可以说明如果只有一组"1-0"那么异或出来的结果会比x大因为最高位不动 而"0-1"又全部实现, 异或结果只会比原来x大,只有当"1-0"组数>=2时,在"0->1"前才会出现0使得异或结果 < x。(这么讲特别抽象,要自己理解) 有解的只需两步
代码实现 有解 :(1) x^y < x,令 y = m, step = 1;
(2) 最高位 "0->1"前有"1-0"两组, 两步。
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void solve()
{
int n, m;
cin >> n >> m;
if ((n ^ m) < n)
{
cout << "1" << endl;
cout << n << " " << m << endl;
return;
}
bitset<64> b1(n), b2(m);
int nu = 0, i;
for (i = 63; i >= 0; i--)
{
if (b1[i] == 1 && b2[i] == 0)
nu++;
else if (b1[i] == 0 && b2[i] == 1)
{
if (nu <= 1)
{
cout << "-1" << endl;
return;
}
}
}
cout << "2" << endl;
int flag = 0;
for (i = 63; i >= 0; i--)
{
if (b1[i] != b2[i])
{
flag = i;
break;
}
}
int t = (n ^ m) ^ (1ll << flag);
cout << n << " " << (n ^ t) << " " << m << endl;
}
signed main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
(给ye干沉默了,bi[x] == '1',死都看不出来)
D2. XOR Break — Game Version
交互题
将所给数 拆成 p1^p2 = p 且 0 < p1 < p, 0 < p2 < p
不能绕在怎么异或出来数字,而是什么时候一定赢
当n二进制中count = 1, 先手必败。
cout = 2,先手必胜。
考虑n中1的个数为偶数时,我为先手,一定分为 奇数+奇数 让BOB选的一定是奇数,他怎么分都是奇数+偶数,我一定选择偶数的那个, 而考虑在63轮内结束,我每次从最高位取一个1,无论BOB怎么取数每次一定是减少的,可以在63次内结束(2e63 <> 1e19)
反之 n中1的个数为奇数时,后手胜利。
(考察的是数学,我一定会赢就是设好了陷阱给BOB)
//md你不能保证一开始BOB就能分的出来┗|`O′|┛ 嗷~~
code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void solve()
{
int n, x, y, i, ii;
cin >> n;
bitset<64> bo(n);
if (bo.count() % 2)
{
cout << "second" << endl;
cin >> x >> y;
if (x == 0 && y == 0)
//特判 一开始BOB就分不出来相当于后面的while
{
return;
}
if (bitset<64>(x).count() % 2)
n = y;
else
n = x;
}
else
cout << "first" << endl;
do
{
bo = n;
for (i = 64; i >= 0; i--)
{
if (bo[i])
{
ii = i;
break;
}
}
int t = (1ll << i);
cout << t << " " << (t ^ n) << endl;
cin >> x >> y;
if (bitset<64>(x).count() % 2)
n = y;
else
n = x;
} while (x && y);
}
signed main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
E. Weird LCM Operations
https://www.cnblogs.com/hwy0622/p/18050338/cf1934 //芜湖博主写得很清晰
//大佬说"有关 gcd,lcm 的题目一定要尽量构造 互质 的情况"!!!!
原数组[1, n/2], 都可以通过(n/2, n)来构造gcd
那么就看[n/2, n]这一块。
就三个三个抽出来,n-2, n-1, n.
当n为奇数时,((n-1)n, (n-2)n, (n-1)*(n-2)) 两两gcd可得。
当n为偶数时,会有公因数2,但是n有可能是4的倍数,n/2可能还是有公共因子2,就考虑(n-2) divide 2此时一定是奇数(n-2不为4的倍数),((n-2)/2, n-1, n)操作后,将n-2, n-1, n, (n-2)/2
做gcd。当n不是4的倍数,就直接(n-2, n-1, n/2)。
当n/2不能完全三个三个分组就先(1, n, n -1), 也是直接出的。
//大佬还是大佬
#include <bits/stdc++.h>
using namespace std;
int n, T, m, a;
void solve()
{
cin >> n;
m = (n + 1) / 2;
a = n;
cout << (m + 2) / 3 << endl;
if (m % 3)
{
cout << "1 " << n - 1 << " " << n << endl;
a -= 2;
}
while (a + a > n)
{
if (a % 2 == 1)
cout << a << " " << a - 1 << " " << a - 2 << endl;
else if (a % 4)
cout << a / 2 << " " << a - 1 << " " << a - 2 << endl;
else
cout << a / 2 - 1 << " " << a - 1 <<" "<< a << endl;
a -= 3;
}
}
void sol()
{
cin >> n;
m = (n + 1) / 2, a = n;
cout << (m + 2) / 3 << '\n';
if (m % 3)
cout << 1 << ' ' << n - 1 << ' ' << n << '\n', a -= 2;
while (a + a > n)
{
if (a & 1)
cout << a << ' ' << a - 1 << ' ' << a - 2 << '\n';
else if (a % 4)
cout << a / 2 << ' ' << a - 1 << ' ' << a - 2 << '\n';
else
cout << a / 2 - 1 << ' ' << a - 1 << ' ' << a << '\n';
a -= 3;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--)
{
solve();
}
return 0;
}
标签:cout,int,Codeforces,long,--,solve,补题,y1,931div2
From: https://www.cnblogs.com/yingtaoqqq/p/18057428