QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#96967 | #6324. Expanded Hull | applese | WA | 117ms | 3876kb | C++14 | 9.6kb | 2023-04-16 12:23:55 | 2023-04-16 12:23:57 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
#define double long double
const double eps = 1e-12;
int Dcmp(double x) {
return x < -eps ? -1 : x > eps ? 1 : 0;
}
struct Point {
double x, y, z;
Point(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
bool operator == (const Point &rhs) const {
return Dcmp(x - rhs.x) == 0 && Dcmp(y - rhs.y) == 0 && Dcmp(z - rhs.z) == 0;
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y, z + rhs.z);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y, z - rhs.z);
}
double operator * (const Point &rhs) const {
return x * rhs.x + y * rhs.y + z * rhs.z;
}
Point operator ^ (const Point &rhs) const {
return Point(y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x);
}
Point operator * (const double &k) const {
return Point(x * k, y * k, z * k);
}
Point operator / (const double &k) const {
return Point(x / k, y / k, z / k);
}
double len2() {
return x * x + y * y + z * z;
}
double len() {
return sqrt(len2());
}
Point Unit() {
return *this / len();
}
};
int Cmp(Point a, Point b) {
return Dcmp(a.z - b.z) == 0 ? Dcmp(a.x - b.x) == 0 ? Dcmp(a.y - b.y) < 0 : Dcmp(a.x - b.x) < 0 : Dcmp(a.z - b.z) < 0;
}
double Volume(Point a, Point b, Point c, Point d) {
return ((b - a) ^ (c - a)) * (d - a);
}
struct Line {
Point s, t;
Line(Point s = Point(), Point t = Point()) : s(s), t(t) {}
};
vector<Line> vl;
namespace Hull {
const int maxn = 205;
struct Face {
int a, b, c, ok;
};
int n;
Point P[maxn];
int num;
Face F[8 * maxn];
int g[maxn][maxn];
double Dblcmp(Point p, Face f) {
Point p1 = P[f.b] - P[f.a], p2 = P[f.c] - P[f.a], p3 = p - P[f.a];
return (p1 ^ p2) * p3;
}
void Dfs(int p, int now);
void Deal(int p, int a, int b) {
int f = g[a][b];
Face add;
if(F[f].ok) {
if(Dblcmp(P[p], F[f]) > eps) {
Dfs(p, f);
}
else {
add.a = b, add.b = a, add.c = p, add.ok = 1, g[p][b] = g[a][p] = g[b][a] = num, F[num ++] = add;
}
}
}
void Dfs(int p, int now) {
F[now].ok = false;
Deal(p, F[now].b, F[now].a);
Deal(p, F[now].c, F[now].b);
Deal(p, F[now].a, F[now].c);
}
bool Same(int s, int t) {
Point &a = P[F[s].a], &b = P[F[s].b], &c = P[F[s].c];
return Dcmp(Volume(a, b, c, P[F[t].a])) == 0 && Dcmp(Volume(a, b, c, P[F[t].b])) == 0 && Dcmp(Volume(a, b, c, P[F[t].c])) == 0;
}
void Create() {
num = 0;
Face add;
int flag = 1;
for(int i = 1; i < n; ++ i) {
if(!(P[0] == P[i])) {
swap(P[1], P[i]);
flag = 0;
break;
}
}
if(flag)
return;
flag = 1;
for(int i = 2; i < n; ++ i) {
if(Dcmp(((P[1] - P[0]) ^ (P[i] - P[0])).len()) == 1) {
swap(P[2], P[i]);
flag = 0;
break;
}
}
if(flag)
return;
flag = 1;
for(int i = 3; i < n; ++ i) {
if(Dcmp(Volume(P[0], P[1], P[2], P[i]))) {
swap(P[3], P[i]);
flag = 0;
break;
}
}
if(flag)
return;
for(int i = 0; i < 4; ++ i) {
add.a = (i + 1) % 4;
add.b = (i + 2) % 4;
add.c = (i + 3) % 4;
add.ok = 1;
if(Dblcmp(P[i], add) > 0)
swap(add.b, add.c);
g[add.a][add.b] = g[add.b][add.c] = g[add.c][add.a] = num;
F[num ++] = add;
}
for(int i = 4; i < n; ++ i) {
for(int j = 0; j < num; ++ j) {
if(F[j].ok && Dblcmp(P[i], F[j]) > eps) {
Dfs(i, j);
break;
}
}
}
int tmp = num;
num = 0;
for(int i = 0; i < tmp; ++ i)
if(F[i].ok)
F[num ++] = F[i];
}
int vis[maxn][maxn];
void Extract() {
for(int i = 0; i < num; ++ i) {
int p = F[i].a, q = F[i].b;
if(Cmp(P[q], P[p]))
swap(p, q);
if(!vis[p][q])
vis[p][q] = 1, vl.push_back(Line(P[p], P[q]));
p = F[i].b, q = F[i].c;
if(Cmp(P[q], P[p]))
swap(p, q);
if(!vis[p][q])
vis[p][q] = 1, vl.push_back(Line(P[p], P[q]));
p = F[i].a, q = F[i].c;
if(Cmp(P[q], P[p]))
swap(p, q);
if(!vis[p][q])
vis[p][q] = 1, vl.push_back(Line(P[p], P[q]));
}
}
}
int n;
long long k, ans[5];
const int maxn = 2005, lim = 200;
vector<int> add[maxn], del[maxn];
vector<Line> nowl;
set<int> s;
struct P2 {
double x, y;
P2(double x = 0, double y = 0) : x(x), y(y) {}
bool operator == (const P2 &rhs) const {
return Dcmp(x - rhs.x) == 0 && Dcmp(y - rhs.y) == 0;
}
bool operator < (const P2 &rhs) const {
return Dcmp(x - rhs.x) == 0 ? Dcmp(y - rhs.y) < 0 : Dcmp(x - rhs.x) < 0;
}
P2 operator + (const P2 &rhs) const {
return P2(x + rhs.x, y + rhs.y);
}
P2 operator - (const P2 &rhs) const {
return P2(x - rhs.x, y - rhs.y);
}
double operator ^ (const P2 &rhs) const {
return x * rhs.y - y * rhs.x;
}
P2 operator * (const double &k) const {
return P2(x * k, y * k);
}
P2 operator / (const double &k) const {
return P2(x / k, y / k);
}
double len2() {
return x * x + y * y;
}
};
int Left(const P2 &a, const P2 &b, const P2 &c) {
return Dcmp((b - a) ^ (c - a)) >= 0;
}
P2 base;
vector<P2> Convex(vector<P2>a) {
int n = a.size(), cnt = 0;
if(n < 3)
return a;
base = a[0];
for(auto p : a)
if(make_pair(p.x, p.y) < make_pair(base.x, base.y))
base = p;
sort(a.begin(), a.end(), [](const P2 &a, const P2 &b) {
int d = Dcmp((a - base) ^ (b - base));
if(d)
return d > 0;
return (a - base).len2() < (b - base).len2();
});
vector<P2>res;
for(int i = 0; i < n; ++ i) {
while(cnt > 1 && Left(res[cnt - 2], a[i], res[cnt - 1]))
-- cnt, res.pop_back();
res.push_back(a[i]), ++ cnt;
}
return res;
}
long long Calc(int mul) {
int nowlim = lim * mul;
for(int i = 0; i <= 2 * nowlim; ++ i)
add[i].clear(), del[i].clear();
nowl.resize(vl.size());
// cerr << vl.size() << endl;
for(int i = 0; i < (int)vl.size(); ++ i) {
nowl[i] = Line(vl[i].s * mul, vl[i].t * mul);
// cerr << "L: " << endl;
// cerr << nowl[i].s.x << " " << nowl[i].s.y << " " << nowl[i].s.z << endl;
// cerr << nowl[i].t.x << " " << nowl[i].t.y << " " << nowl[i].t.z << endl;
add[int(ceil(nowl[i].s.z)) + nowlim].push_back(i);
del[int(floor(nowl[i].t.z)) + nowlim].push_back(i);
}
long long ans = 0;
for(int i = 0; i <= 2 * nowlim; ++ i) {
for(auto j : add[i])
s.insert(j);
vector<P2> v;
v.clear();
int z = i - nowlim;
for(auto x : s) {
int f = 0;
if(Dcmp(nowl[x].s.z - z) == 0)
v.push_back(P2(nowl[x].s.x, nowl[x].s.y)), f = 1;
if(Dcmp(nowl[x].t.z - z) == 0)
v.push_back(P2(nowl[x].t.x, nowl[x].t.y)), f = 1;
if(!f) {
assert(Dcmp(nowl[x].s.z - z) < 0 && Dcmp(nowl[x].t.z - z) > 0);
Point p = nowl[x].s + (nowl[x].t - nowl[x].s) / (nowl[x].t.z - nowl[x].s.z) * (z - nowl[x].s.z);
v.push_back(P2(p.x, p.y));
}
}
if(!v.size())
continue;
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
v = Convex(v);
// cerr << "At z = " << z << ": Convex is ";
// for(auto p : v)
// cerr << "(" << p.x << ", " << p.y << ")" << endl;
// cerr << endl;
int pos = 0, sz = v.size();
for(int j = 1; j < sz; ++ j)
if(v[pos] < v[j])
pos = j;
#define Pre(p) ((p + sz - 1) % sz)
#define Nxt(p) ((p + 1) % sz)
int upp = 0, dwp = 0;
for(int x = -nowlim; x <= nowlim; ++ x) {
while(upp != pos && Dcmp(v[Pre(upp)].x - x) <= 0)
upp = Pre(upp);
while(dwp != pos && Dcmp(v[Nxt(dwp)].x - x) <= 0)
dwp = Nxt(dwp);
int mx = -nowlim - 1, mn = nowlim + 1;
if(Dcmp(v[upp].x - x) <= 0) {
if(upp != pos) {
P2 s = v[upp], t = v[Pre(upp)], w = s + (t - s) / (t.x - s.x) * (x - s.x);
if(Dcmp(w.y - round(w.y)) == 0)
mx = round(w.y);
else
mx = floor(w.y);
}
else if(Dcmp(v[upp].x - x) == 0) {
double wy = v[upp].y;
if(Dcmp(wy - round(wy)) == 0)
mx = round(wy);
else
mx = floor(wy);
}
}
if(Dcmp(v[dwp].x - x) <= 0) {
if(dwp != pos) {
P2 s = v[dwp], t = v[Nxt(dwp)], w = s + (t - s) / (t.x - s.x) * (x - s.x);
if(Dcmp(w.y - round(w.y)) == 0)
mn = round(w.y);
else
mn = ceil(w.y);
}
else if(Dcmp(v[dwp].x - x) == 0) {
double wy = v[dwp].y;
if(Dcmp(wy - round(wy)) == 0)
mn = round(wy);
else
mn = ceil(wy);
}
}
if(mn <= mx) {
// cerr << "At x = " << x << ": mn = " << mn << " mx = " << mx << endl;
ans += max(0, mx - mn + 1);
}
}
#undef Pre
#undef Nxt
// cerr << ans << endl;
for(auto j : del[i])
s.erase(s.find(j));
}
// cerr << "Multiply " << mul << ": ans = " << ans << endl;
return ans;
}
const int mod = 998244353;
int Add(int x, int y) {
return (x += y) >= mod ? x - mod : x;
}
int Sub(int x, int y) {
return (x -= y) < 0 ? x + mod : x;
}
int Mul(int x, int y) {
return 1ll * x * y % mod;
}
int Pow(int x, int y) {
int res = 1;
for(; y; x = Mul(x, x), y >>= 1)
if(y & 1)
res = Mul(res, x);
return res;
}
int main() {
scanf("%d%lld", &n, &k);
for(int i = 0, x, y, z; i < n; ++ i) {
scanf("%d%d%d", &x, &y, &z);
Hull :: P[i] = Point(x, y, z);
}
Hull :: n = n;
Hull :: Create();
// cerr << Hull :: num << endl;
Hull :: Extract();
// for(auto l : vl)
// cerr << "(" << l.s.x << ", " << l.s.y << ", " << l.s.z << ") (" << l.t.x << ", " << l.t.y << ", " << l.t.z << ")" << endl;
ans[0] = 1;
// Calc(1);
for(int i = 1; i <= 3; ++ i)
ans[i] = Calc(i);
if(k <= 3)
printf("%lld\n", ans[k]);
else {
int ret = 0;
for(int i = 0; i <= 3; ++ i) {
int up = ans[i] % mod, dn = 1;
for(int j = 0; j <= 3; ++ j) {
if(i == j)
continue;
up = Mul(up, Sub(k % mod, j));
dn = Mul(dn, Sub(i, j));
}
ret = Add(ret, Mul(up, Pow(dn, mod - 2)));
}
printf("%d\n", ret);
}
}
详细
Test #1:
score: 100
Accepted
time: 0ms
memory: 3724kb
input:
4 2 0 0 0 1 0 0 0 1 0 0 0 1
output:
10
result:
ok 1 number(s): "10"
Test #2:
score: 0
Accepted
time: 2ms
memory: 3732kb
input:
4 10000 0 0 0 1 0 0 0 1 0 0 0 1
output:
59878050
result:
ok 1 number(s): "59878050"
Test #3:
score: 0
Accepted
time: 3ms
memory: 3704kb
input:
8 314159265358979 5 -3 -3 -5 -3 -3 0 5 -3 0 0 10 4 2 6 -4 2 6 0 -5 6 0 0 -5
output:
152811018
result:
ok 1 number(s): "152811018"
Test #4:
score: 0
Accepted
time: 79ms
memory: 3780kb
input:
100 1 0 0 77 0 0 -195 0 0 -194 0 0 -112 0 0 -192 0 0 62 0 0 73 0 0 188 0 0 -150 0 0 -26 0 0 -164 0 0 -142 0 0 -90 200 1 0 0 0 50 0 0 111 0 0 -133 0 0 91 0 0 -70 0 0 46 0 0 175 -200 -67 0 0 0 128 0 0 170 0 0 76 0 0 -28 0 0 47 0 0 -196 0 0 45 0 0 -136 0 0 96 0 0 24 0 0 -29 0 0 -141 0 0 -84 0 0 -99 0 0...
output:
882531
result:
ok 1 number(s): "882531"
Test #5:
score: 0
Accepted
time: 85ms
memory: 3756kb
input:
82 333333333 98 99 168 -106 -105 -172 113 114 193 -13 -12 -17 -115 -114 -187 71 72 123 -70 -69 -112 95 96 163 -85 -84 -137 -28 -27 -42 -31 -30 -47 -200 -67 0 -121 -120 -197 -52 -51 -82 -112 -111 -182 110 111 188 44 45 78 86 87 148 104 105 178 -73 -72 -117 47 48 83 62 63 108 -103 -102 -167 56 57 98 1...
output:
767480931
result:
ok 1 number(s): "767480931"
Test #6:
score: 0
Accepted
time: 95ms
memory: 3876kb
input:
100 1 -63 -39 51 -36 -104 70 9 -77 34 115 -153 19 -161 141 10 157 -149 -4 -82 -92 87 14 114 -64 -176 -68 122 -7 -179 93 -182 200 -9 173 97 -135 0 -1 200 -83 -189 136 117 69 -93 -3 -113 58 183 -179 -2 -52 -184 118 -107 89 9 -24 -48 36 -111 87 12 -143 -173 158 -176 -78 127 -96 162 -33 147 -111 -18 -92...
output:
9771107
result:
ok 1 number(s): "9771107"
Test #7:
score: 0
Accepted
time: 117ms
memory: 3820kb
input:
100 1159111449 82 82 90 181 181 -85 70 70 -20 1 1 0 190 190 56 -83 -83 40 -89 -89 39 136 136 146 -195 -195 47 50 50 -99 -101 -101 -161 162 162 146 23 23 152 181 181 -91 -73 -73 -5 -105 -105 6 155 155 -136 152 152 -190 -33 -33 -137 55 55 41 3 3 -199 -168 -168 -177 -111 -111 115 171 171 8 131 131 123 ...
output:
681451260
result:
ok 1 number(s): "681451260"
Test #8:
score: -100
Wrong Answer
time: 108ms
memory: 3696kb
input:
8 1 200 200 200 -200 -200 -200 200 -200 -200 -200 200 200 -200 200 -200 200 200 -200 200 -200 200 -200 -200 200
output:
64320801
result:
wrong answer 1st numbers differ - expected: '64481201', found: '64320801'