- SleepingCup 的博客
-
Sleeping Cup #4 Editor
- @ 2026-3-3 19:32:46
A - Football Loser
看清总评价的计算公式后利用 struct 和 sort 排序即可。
为了避免精度误差,建议按 (将原来的公式除以 )计算总评价,此时需要使用 long long。(当然了,直接使用 double 或 long double 也是一个不错的选择。)
#include <bits/stdc++.h>
using namespace std;
const int A = 20 + 2;
struct Team
{
string b;
int m;
int n;
int t;
long long k;
};
Team team[A];
bool cmp(Team x, Team y)
{
return x.k > y.k;
}
int main()
{
freopen("football.in", "r", stdin);
freopen("football.out", "w", stdout);
int T;
cin >> T;
while (T--)
{
int a;
cin >> a;
for (int i = 1; i <= a; i++)
{
cin >> team[i].b >> team[i].m >> team[i].n >> team[i].t;
team[i].k = 1ll * team[i].t * (2ll * team[i].m + 1ll * team[i].n);
}
sort(team + 1, team + a + 1, cmp);
for (int i = 1; i <= a; i++)
{
cout << team[i].b;
if (i != a) cout << ' ';
}
cout << endl;
}
return 0;
}
B - Tangent Dancer
显然 。考虑一次移动中轨迹的斜率 。画图可知,当 $\varphi \in (-\dfrac{\pi}{2},0) \cup (0,\dfrac{\pi}{2})$ 时,:

也就是说,如果直线 的斜率 且存在,那么就可以从 一次性移动到 。
很明显,如果我们第一次移动时选择 ,那么一次移动后的位置 与终点 之间的斜率将会极其接近 ,显然可以从 一次性移动到 。整个过程一共移动了 次,所以答案总是不超过 。
综上,本题的结论是(设 为起点, 为终点):
- 与 重合时答案为 ;
- 且存在时答案为 ;
- 以上两个条件都不满足时答案为 。
#include <bits/stdc++.h>
using namespace std;
#define y1 Y1
int steps(int x1, int y1, int x2, int y2)
{
if (x1 == x2 && y1 == y2) return 0;
if (x2 > x1 && y2 - y1 > x2 - x1) return 1;
if (x1 > x2 && y1 - y2 > x1 - x2) return 1;
return 2;
}
int main()
{
freopen("tangent.in", "r", stdin);
freopen("tangent.out", "w", stdout);
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << steps(x1, y1, x2, y2) << endl;
return 0;
}
C - Lottery Cheater
由题意可以列出一个 元异或方程组,且每个方程中只有 个未知数。直接钦定任意一个值后用代入法递归解方程即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 12;
bool ok[N], ans[N];
int n, k;
string s;
void fill(int i)
{
if (ok[i]) return;
ok[i] = true;
int next = (i + k) % n;
ans[next] = ans[i] ^ (s[next] - '0');
fill(next);
}
int main()
{
freopen("lottery.in", "r", stdin);
freopen("lottery.out", "w", stdout);
cin >> n >> k >> s;
reverse(s.begin(), s.end());
k %= n;
for (int i = 0; i <= n - 1; i++)
fill(i);
for (int i = n - 1; i >= 0; i--)
putchar(ans[i] + '0');
return 0;
}
D - Factorial Master
首先特判 的情况。
很明显,当 时,,因此答案不可能大于 。
当 为质数时,由威尔逊定理可得:
因此答案一定是 。
当 为合数时,由题意可知 ,其中 是 的最小素因子。
显然 ,并且答案不大于 ,暴力枚举即可。
最终的时间复杂度是 。
#include <bits/stdc++.h>
using namespace std;
bool prime(int n)
{
if (n == 1) return false;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) return false;
return true;
}
int solve(int n)
{
if (n <= 2) return n - 1;
if (prime(n)) return n - 2;
long long f = 1;
int ans = 1;
for (int i = 2; n % i != 0; i++)
{
f = f * i % n;
if (f == 1) ans = i;
}
return ans;
}
int main()
{
freopen("factorial.in", "r", stdin);
freopen("factorial.out", "w", stdout);
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
cout << solve(n) << endl;
}
return 0;
}