A Alice and Bob
题意
有两堆石子,在其中一堆取 个,对应的另一堆取
个,问谁赢
暴力sg打表 表示有石头
个时是否为先手必胜
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
typedef long long ll;
const int N = 5e3 + 7;
ll sg[N][N];
signed main() {
rep(i, 0, 5000) rep(i, 0, 5000) if (sg[i][j] == 0) {
for (int k = 1; k + i <= 5000; k++)
for (int s = 0; s * k + j <= 5000; s++)
sg[i + k][j + s * k] = 1;
for (int k = 1; k + j <= 5000; k++)
for (int s = 0; s * k + i <= 5000; s++)
sg[i + s * k][j + k] = 1;
}
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
sg[n][m] ? puts("Bob") : puts("Alice");
}
return 0;
} B Ball Dropping
题意
有一个空心圆台,从大口投入一个半径为R的球,问球是否能穿过圆台,若不能,问球心离底面的距离
侧面图
如果圆能穿过即 ,这个很容易,以下讨论不能穿过的情况
通过两次相似可以求得
这样简单得出了答案
#include <bits/stdc++.h>
using namespace std;
signed main() {
double r, a, b, h;
scanf("%lf%lf%lf%lf", &r, &a, &b, &h);
if (2.0 * r < b) {
puts("Drop");
return 0;
}
double th = atan(h / ((a - b) / 2.0));
double dis = r * sin(th), d = r * cos(th);
double H = 1.0 * a * h / (a - b);
double ds = 2.0 * dis * H / a;
double ans = ds + d - (H - h);
puts("Stuck");
printf("%.10lf\n", ans);
return 0;
} D Determine the Photo Position
题意
给一个01矩阵,和一个长度为 m 的只包含字符 ‘2’ 的字符串,让这个字符串放入矩阵中
这个字符串是放入其中一行的一段连续的 0 中,问有多少种插入方式
暴力模拟
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
typedef long long ll;
signed main() {
int n, m, ans = 0;
cin >> n >> m;
string s;
rep(i, 1, n) {
cin >> s;
int cnt = 0;
rep(j, 0, s.length() - 1) {
if (s[j] == '1') {
if (cnt >= m)
ans += cnt - m + 1;
cnt = 0;
continue;
}
if (s[j] == '0')
cnt++;
}
if (cnt >= m)
ans += cnt - m + 1;
}
cin >> s;
cout << ans << endl;
return 0;
} F Find 3-friendly Integers
题意
定义一个 3-friendly number :在数中连续的一段是否能被3整除
找规律发现在 100 之后的数都是 3-friendly number 也可以说是88
之后暴力打表前 100 ,然后分类处理即可
勇士也可以树形dp
#include <bits/stdc++.h>
using namespace std;
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", x)
#define fi first
#define se second
#define eb emplace_back
#define endl '\n'
#define int ll
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define rrep(i, j, k) for (ll i = (ll)(j); i >= (ll)(k); i--)
#define mem(x, y) memset(x, y, sizeof(x))
typedef long double ld;
typedef long long ll;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
const ld pi = acos(-1);
const int mod = 1e9 + 7;
const ll INF = LLONG_MAX;
const int N = 1e5 + 7;
ll a[N];
bool chk(int i) {
if (i % 3 == 0)
return 1;
int t = i;
while (t) {
if (t % 10 % 3 == 0)
return 1;
t /= 10;
}
return 0;
}
void init() {
}
void solve() {
int l, r;
cin >> l >> r;
if (r > 100)
if (l >= 100)
cout << r - l + 1 << endl;
else
cout << r - 100 + a[100] - a[l - 1] << endl;
else if (r <= 100)
cout << a[r] - a[l - 1] << endl;
}
signed main() {
rep(i, 1, 100) a[i] = chk(i);
rep(i, 1, 100) a[i] = a[i - 1] + a[i];
int t;
cin >> t;
while (t--)
solve();
return 0;
} G Game of Swapping Numbers
题意
给两个数组,求
这里简单讲下我的理解
设
当 的时候交换
对答案的贡献是无用的
当 的时候交换
对答案的贡为
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
typedef long long ll;
const int N = 1e6 + 7;
ll a[N], b[N], minn[N], maxn[N];
void solve() {}
signed main() {
ll n, k, sum = 0;
cin >> n >> k;
rep(i, 1, n) cin >> a[i];
rep(i, 1, n) cin >> b[i], sum += abs(a[i] - b[i]);
rep(i, 1, n) minn[i] = min(a[i], b[i]), maxn[i] = max(a[i], b[i]);
sort(minn + 1, minn + n + 1, greater<int>());
sort(maxn + 1, maxn + n + 1);
for (int i = 1; i <= min(n, k); i++)
if (maxn[i] < minn[i])
sum += (minn[i] - maxn[i]) * 2;
printf("%lld", sum);
return 0;
} H Hash Function
题意
给定一个集合,求一个数 mod 使得 集合中任意两个数
上述问题可以转化为 任意的两个数的差对 mod 取余不等于 0
可知任意两个数差值的因子都不能满足条件,即找出最小的非****的因子
朴素求任意两个数的差时间复杂度为
于是可以考虑用 FFT 加速
将多项式中第 项系数取值为 1,其余系数为 0 该多项式即为
对应多项式 为 第
为 1,其余系数为 0,则考虑通过加上一个常数抵消负数
于是 的结果中,有系数的项
即表示:集合中任意两个数的差值
存在
之后从开始枚举因子即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
typedef long long ll;
typedef complex<double> cp;
const int lim = 1 << 21;
const double pi = acos(-1);
cp a[lim], b[lim]; // 多项式 A B
int rev[lim];
void fft(cp *a, int n, int inv) {
int bit = 0;
while ((1 << bit) < n)
bit++;
rep(i, 0, n - 1) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
if (i < rev[i])
swap(a[i], a[rev[i]]);
}
for (int mid = 1; mid < n; mid *= 2) {
cp temp(cos(pi / mid), inv * sin(pi / mid));
for (int i = 0; i < n; i += mid * 2) {
cp omega(1, 0);
for (int j = 0; j < mid; ++j, omega *= temp) {
cp x = a[i + j], y = omega * a[i + j + mid];
a[i + j] = x + y, a[i + j + mid] = x - y;
}
}
}
if (inv == -1)
for (int i = 0; i < lim; ++i)
a[i].real(a[i].real() / n);
}
bool vis[lim];
const int P = 500001;
bool check(int x) {
for (int i = x; i <= P; i += x)
if (vis[i] == 1)
return 0;
return 1;
}
signed main() {
int t, n, m;
cin >> n;
rep(i, 0, n - 1) {
cin >> t;
a[t] = {1, 0};
b[P - t] = {1, 0};
}
int num = 1 << 20;
fft(a, num, 1);
fft(b, num, 1);
rep(i, 0, num - 1) a[i] *= b[i];
fft(a, num, -1);
rep(i, 0, num) {
t = floor(a[i].real() + 0.5);
if (t > 0)
vis[abs(i - P)] = 1;
}
rep(i, n, P) if (check(i)) {
printf("%d\n", i);
break;
}
return 0;
} K Knowledge Test about Match
题意
给定两个长度为 的序列
,保证
。希望调整序列
中的元素顺序,使得调整后的元素顺序为
最小。
正解为KM算法,但时间复杂度为 。
因此题面不要求取得 最小值,允许存在 4%的误差,此时考虑贪心的解法,凑出
尽可能小即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define mem(x, y) memset(x, y, sizeof(x))
typedef long long ll;
const int N = 1e4 + 7;
ll a[N], res[N], buc[N];
bool vis[N];
void solve() {
mem(res, -1), mem(vis, 0), mem(buc, 0);
int n, x;
cin >> n;
rep(i, 1, n) cin >> x, buc[x]++;
rep(i, 0, n - 1) { // 枚举差值
rep(j, 0, n - 1) { // 看 a_j 是否能够匹配
if (res[j] != -1)
continue;
if (j >= i and buc[j - i]) {
buc[j - i]--, res[j] = j - i;
} else if (buc[j + i]) {
buc[j + i]--, res[j] = j + i;
}
}
}
rep(i, 0, n - 1) cout << res[i] << (i == n - 1 ? '\n' : ' ');
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
} 另外还有一种类似冒泡排序的算法:先假定一个可能的序列,然后枚举两两交换后对 的影响,如果两个数交换后
跟小,则交换。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define mem(x, y) memset(x, y, sizeof(x))
typedef long long ll;
const int N = 1e4 + 7;
int a[N];
inline long double work(int x, int y) { return sqrt(abs(x - y)); }
void solve() {
int n;
cin >> n;
rep(i, 0, n - 1) cin >> a[i];
for (int k = 1; k <= 3; ++k) // 注意要多执行几次,一次操作精度不够
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (work(i, a[i]) + work(j, a[j]) > work(j, a[i]) + work(i, a[j]))
swap(a[i], a[j]);
for (int i = 0; i < n; ++i)
cout << a[i] << ' ';
cout << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
} 
京公网安备 11010502036488号