「SCOI2011」飞镖
一、前言
[和谐美好]选择结构题
二、题解
一眼做法,枚举系数,然后解线性方程。
然后就贼[和谐美好]难打。
先考虑三个飞镖都扔完
第一个 { } \{ \} {} 里的东西是系数序列,第二个 { } \{ \} {} 里的东西是自变量上确界序列(下确界都是 1 1 1)
case 1: 只有一种系数,且一定有一个 2 m 2m 2m。
{ 2 m , i , i } \{ 2m, i, i \} {2m,i,i} { 1 , k , k } \{ 1, k, k \} {1,k,k}
case 2: 只有两种系数,且一定有一个 2 m 2m 2m
{ 2 m , i , j } \{ 2m, i, j \} {2m,i,j} { 1 , k , k } \{ 1, k, k \} {1,k,k}
case 3: 只有两种系数,且一定没有 2 m 2m 2m
{
i
,
2
,
2
}
\{ i, 2, 2 \}
{i,2,2}
{
k
,
k
,
k
}
\{ k, k, k \}
{k,k,k}
{
i
,
i
,
2
}
\{ i, i, 2 \}
{i,i,2}
{
k
,
k
,
k
}
\{ k, k, k \}
{k,k,k}
case 4: 有三种系数
{ 1 , 2 , 3 } \{ 1, 2, 3 \} {1,2,3} { k , k , k } \{ k, k, k \} {k,k,k}
case 5: 一种系数都没有
{ m , m , m } \{ m, m, m \} {m,m,m} { 2 , 2 , 2 } \{ 2,2,2 \} {2,2,2} (第一个变量的系数强制为 2 2 2)
{ m , m , m } \{ m, m, m \} {m,m,m} { 0 , 0 , 0 } \{ 0,0,0 \} {0,0,0}
对于 C a s e 1 — 3 Case 1—3 Case1—3,我们相当于解一个类似于如下的线性方程。 a x + b y = c ax + by = c ax+by=c
我们可以写出它的通解
{ x = x 0 + b g c d ( a , b ) k y = y 0 − a g c d ( a , b ) k {x=x0+gcd(a,b)bky=y0−gcd(a,b)ak
ps: x 0 , y 0 x_0,y_0 x0,y0 表示一组满足要求的特殊解。
这时我们相当于要找一组解,满足 x ∈ [ l 1 , r 1 ] , y ∈ [ l 2 , r 2 ] x \in [l_1, r_1], y \in [l_2, r_2] x∈[l1,r1],y∈[l2,r2]。
由于只是判断存在性,我们只需要枚举 x x x 满足要求的最大和最小值,算出对应的 y y y 的值,判断是否在区间内,然后交换 x , y x,y x,y 和定义域区间,再判断一下,只要有一个满足就说明有解。
对于 C a s e 4 Case4 Case4 我们只需要满足 x ∈ [ 2 , 6 k ] x \in [2, 6k] x∈[2,6k] 即可。
对于 C a s e 5 Case5 Case5 我们直接特判
为了代码简洁,投掷次数不足三次的就多传了一个参(标记是否允许等于零),如果能理清枚举思路的话还好,如果没有理清那么我的代码可能就失去了可读性……
三、参考代码
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define rep(i,j,k) for (int i = (j); i <= (k); i++)
#define per(i,j,k) for (int i = (j); i >= (k); i--)
template <typename T>
void read (T &x) {
x = 0;
T f = 1; char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
read (x); read (args...);
}
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return (x > 0 ? x : -x); }
LL exgcd (LL a, LL b, LL &x, LL &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
LL res = exgcd (b, a % b, y, x);
y -= (a / b) * x;
return res;
}
const int Maxn = 3;
const int Maxm = 5;
int t;
LL a[Maxn + 5][Maxm + 5];
LL x[Maxm + 5][Maxm + 5], y[Maxm + 5][Maxm + 5], _gcd[Maxm + 5][Maxm + 5];
bool check (LL Limit, LL k1, LL x1, LL X, bool zero1) {
if (X % k1) return 0;
X /= k1;
LL l, r;
if (zero1) l = 0;
else l = x1;
r = x1 * Limit;
if (l <= X && X <= r) return 1;
else return 0;
}
bool judge (LL X, LL Y, LL DX, LL DY, LL num, LL l1, LL r1, LL l2, LL r2) {
X += DX * num, Y -= DY * num;
return (l1 <= X && X <= r1) && (l2 <= Y && Y <= r2);
}
bool check (LL Limit, LL k1, LL x1, LL k2, LL x2, LL X, bool zero1, bool zero2) {
LL l1 = x1, r1 = x1 * Limit, l2 = x2, r2 = x2 * Limit;
if (zero1) l1 = 0;
if (zero2) l2 = 0;
if (X % _gcd[k1][k2]) return 0;
LL f = x[k1][k2] * (X / _gcd[k1][k2]), s = y[k1][k2] * (X / _gcd[k1][k2]);
LL df = k2, ds = k1;
bool fl = judge (f, s, df, ds, ceil ((l1 - f) * 1.0 / df), l1, r1, l2, r2) | judge (f, s, df, ds, floor ((r1 - f) * 1.0 / df), l1, r1, l2, r2);
swap (f, s);
swap (df, ds);
swap (l1, l2);
swap (r1, r2);
fl |= judge (f, s, df, ds, ceil ((l1 - f) * 1.0 / df), l1, r1, l2, r2) | judge (f, s, df, ds, floor ((r1 - f) * 1.0 / df), l1, r1, l2, r2);
return fl;
}
bool check_three (LL Limit, LL x) {
return 2 <= x && x <= 2 * Limit + 3 * Limit + Limit;
}
signed main () {
read (t);
rep (i, 1, 3)
rep (j, 1, 5)
read (a[i][j]);
rep (i, 1, 3)
rep (j, 1, 3)
_gcd[i][j] = exgcd (i, j, x[i][j], y[i][j]);
int cnt = 0;
rep (step, 1, t) {
LL k = a[1][5], m = a[2][5], x = a[3][5];
rep (i, 1, 3) a[i][5] = ((a[i][1] * a[i][5] % a[i][4] * a[i][5] % a[i][4] + a[i][2] * a[i][5] % a[i][4] + a[i][3]) % a[i][4]) + 20;
bool fl = 0;
rep (i, 1, 3) {
if (check (k, i, 2, x - 2 * m, 1)) fl = 1;
if (check (k, i, 1, x - 2 * m - m, 1)) fl = 1;
if (check (k, i, 1, x - 2 * m - 2 * m, 1)) fl = 1;
}
rep (i, 1, 3)
rep (j, 1, 3) {
if (check (k, i, 1, j, 1, x - 2 * m, 1, 1)) fl = 1;
}
rep (i, 1, 3) {
if (check (k, i, 1, 2, 2, x, 1, 0)) fl = 1;
if (check (k, i, 2, 2, 1, x, 1, 0)) fl = 1;
if (check (k, i, 1, 2, 1, x - m, 1, 0)) fl = 1;
if (check (k, i, 1, 2, 1, x - 2 * m, 1, 1)) fl = 1;
}
if (check_three (k, x)) fl = 1;
if (((2 <= x / m && x / m <= 6) || (x / m == 0)) && x % m == 0) fl = 1;
cnt += fl;
}
cout << cnt;
return 0;
}
讲道理,真的卡常 (虽然只是我的[和谐美好]做法)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通