J. Stone Game
找到所有的谷
然后把整个谷往下拽
需要稍微处理一下峰
另外左右两端也需要处理一下。
实现的时候,直接开一个数组存下最终的唯一指定必败态
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int t, n;
int A[MAXN];
int List[MAXN];
int ss[MAXN];
int ans;
int main()
{
scanf("%d", &t);
for (int _case = 1; _case <= t; ++_case)
{
ans = 0, List[0] = 0;
printf("Case %d: ", _case);
scanf("%d", &n);
A[0] = A[n + 1] = INF;
for (int i = 1; i <= n; ++i)
{
ss[i] = 0;
scanf("%d", &A[i]);
}
for (int i = 1; i <= n; ++i)
{
if (A[i] < A[i-1] && A[i] < A[i+1])
{
List[++List[0]] = i;
}
}
for (int prefA, j, i = 1; i <= List[0]; ++i)
{
ss[List[i]] = 0;
j = List[i], prefA = 0;
while (j > 1 && A[j] < A[j - 1])
{
--j; ++prefA;
if (prefA > ss[j]) ss[j] = prefA;
}
j = List[i], prefA = 0;
while (j < n && A[j] < A[j + 1])
{
++j; ++prefA;
if (prefA > ss[j]) ss[j] = prefA;
}
}
for (int i = 1; i <= n; ++i) ans ^= (A[i] - ss[i]) & 1;
puts(ans ? "Alice" : "Bob");
}
return 0;
}
D. Bits Reverse
翻转连续的三个二进制位其实也就是交换两个相隔一位的二进制位
那么实际上我们可以将一个数的二进制位分成奇数位和偶数位。
接下来剩下的问题就是,只允许交换相邻两位的情况下,最少要交换几次
这个老经典了
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
using namespace std;
#define sysp system("pause");
int t;
long long x, y;
int x_ones[2];
int y_ones[2];
int x_bits[2][100];
int y_bits[2][100];
int x_ptr, y_ptr;
int ans;
int sb;
int main()
{
scanf("%d", &t);
for (int cas = 1; cas <= t; ++cas)
{
printf("Case %d: ", cas);
scanf("%lld%lld", &x, &y);
x_ones[0] = x_ones[1] = y_ones[0] = y_ones[1] = ans = sb = 0;
x_bits[0][0] = x_bits[1][0] = y_bits[0][0] = y_bits[1][0] = 0;
while (x)
{
if (x & 1)
{
++x_ones[sb & 1];
}
x_bits[sb & 1][++x_bits[sb & 1][0]] = x & 1;
x >>= 1;
++sb;
}
sb = 0;
while (y)
{
if (y & 1)
{
++y_ones[sb & 1];
}
y_bits[sb & 1][++y_bits[sb & 1][0]] = y & 1;
y >>= 1;
++sb;
}
if ((x_ones[0] != y_ones[0]) || (x_ones[1] != y_ones[1]))
{
puts("-1");
continue;
}
x_ptr = y_ptr = 1;
while (x_ptr <= x_bits[0][0] && y_ptr <= y_bits[0][0])
{
while (x_bits[0][x_ptr] != 1)
++x_ptr;
while (y_bits[0][y_ptr] != 1)
++y_ptr;
ans += abs(x_ptr - y_ptr);
++x_ptr;
++y_ptr;
}
x_ptr = y_ptr = 1;
while (x_ptr <= x_bits[1][0] && y_ptr <= y_bits[1][0])
{
while (x_bits[1][x_ptr] != 1)
++x_ptr;
while (y_bits[1][y_ptr] != 1)
++y_ptr;
ans += abs(x_ptr - y_ptr);
++x_ptr;
++y_ptr;
}
printf("%d
", ans);
}
// sysp
return 0;
}
G. Greatest Common Divisor
比较有意思
差值这个,懂GCD的都应该懂
然后我直接把差值GCD求出来就拿去用了
实际上应该得对它的每个质因子都做一次。
所以可以先跑一次素数筛,但是我有点懒,这个没必要
除此之外特判巨多
还是多组数据的,非常精神污染
Wrong answer on test 1
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
using namespace std;
#define sysp system("pause");
const int MAXN = 1e5 + 10;
int t, n;
int a[MAXN];
long long ans;
long long g, sqg;
bool brk;
int gcd(int a, int b)
{
return !b ? a : gcd(b, a % b);
}
int main()
{
scanf("%d", &t);
for (int _case = 1; _case <= t; ++_case)
{
printf("Case %d: ", _case);
scanf("%d", &n);
g = 0;
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
n = unique(a + 1, a + 1 + n) - a - 1;
for (int i = 1; i <= n; ++i)
{
if (i < 3)
{
if (i == 1) continue;
g = a[i] - a[i - 1];
continue;
}
g = gcd(g, a[i] - a[i - 1]);
}
if (n == 1)
{
puts(a[1] == 1 ? "1" : "0");
continue;
}
if (g == 1)
{
puts("-1");
continue;
}
if (a[1] % g == 0)
{
puts("0");
continue;
}
sqg = sqrt(g);
if (a[1] % g == 0)
{
puts("0");
continue;
}
ans = 1ll * (a[1] / g + 1) * g - a[1];
brk = 0;
for (int j, i = 2; i <= sqg; ++i)
{
if (g % i == 0)
{
j = g / i;
brk = (a[1] % i == 0) || (a[1] % j == 0);
if (brk)
break;
ans = min(ans, 1ll * (a[1] / i + 1) * i - a[1]);
ans = min(ans, 1ll * (a[1] / j + 1) * j - a[1]);
}
}
if (brk)
{
puts("0");
continue;
}
printf("%lld
", ans);
}
//
// sysp
return 0;
}
H. Hamming Distance
L. Two Ants
样例直接懂完了
貌似又要分类讨论,我就不继续写了