The 2019 ICPC Asia Nanjing Regional Contest
A. A Hard Problem

#include <bits/stdc++.h>
using namespace std;
int main()
{
int cass, n;
for (cin >> cass; cass; cass--)
{
cin >> n;
cout << (n + 1) / 2 + 1 << endl;
}
return 0;
}
B. Chessboard

#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e6 + 10; const int mod = 1e9 + 7; int f[N], inv[N]; int ksm(ll x, ll y) { ll res = 1; while (y) { if (y & 1) res = res * x % mod; x = x * x % mod; y >>= 1; } return res; } int main() { f[0] = 1; for (int i = 1; i < N; i++) f[i] = 1ll * f[i - 1] * i % mod; inv[N - 1] = ksm(f[N - 1], mod - 2); for (int i = N - 2; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; int cass, n, m; for (cin >> cass; cass; cass--) { cin >> n >> m; if (n == 1 || m == 1) cout << 2 << endl; else cout << 4ll * f[m + n - 2] % mod * inv[n - 1] % mod * inv[m - 1] % mod << endl; } return 0; }
C. Digital Path
可以采用记忆化搜索的思路,转化为在一个DAG上按照拓扑做 dp。
f(i,j,k)表示的是以(i, j)为终点,长度为k的路径条数。因为只要长度大于等于4就符合要求,所以长度大于等于4的就可以归为一类,也就是 1 ≤ k ≤ 4。
另外设两个数组 in[i][j] 和 out[i][j],记录每个点的入度和出度,入度为 0 的点为路径的起点,出度为 0 的点为路径的终点。
对图做拓扑序dp,状态转移方程大致可以写成 f(tx, ty, k) = (f(tx, ty, k) + f(x, y, k − 1)) % mod。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
int n, m;
int g[N][N], in[N][N], out[N][N], f[N][N][5];
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &g[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 0; k < 4; k++)
{
int tx = i + dx[k], ty = j + dy[k];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
if (g[tx][ty] == g[i][j] + 1) out[i][j]++;
if (g[tx][ty] == g[i][j] - 1) in[i][j]++;
}
int res = 0;
queue<pair<int, int> PII> que;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!in[i][j]) que.push({i, j}), f[i][j][1] = 1;
while (que.size())
{
auto t = que.front();
que.pop();
int x = t.first, y = t.second;
for (int i = 0; i < 4; i++)
{
int tx = x + dx[i], ty = y + dy[i];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
if (g[tx][ty] == g[x][y] + 1)
{
f[tx][ty][2] = (f[tx][ty][2] + f[x][y][1]) % mod;
f[tx][ty][3] = (f[tx][ty][3] + f[x][y][2]) % mod;
f[tx][ty][4] = (f[tx][ty][4] + f[x][y][3] + f[x][y][4]) % mod;
if (--in[tx][ty] == 0) que.push({tx, ty});
}
}
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!out[i][j]) res = (res + f[i][j][4]) % mod;
printf("%d\n", res);
return 0;
}
D. Holes
E. Observation
F. Paper Grading
G. Poker Game
H. Prince and Princess

#include <bits/stdc++.h>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b >> c;
if (a == 1 && b == 0 && c == 0) cout << "YES" << endl << 0;
else if (a > b + c) cout << "YES" << endl << 2 * (b + c) + 1;
else cout << "NO" << endl;
return 0;
}
I. Space Station
J. Spy
K. Triangle
二分就可以了,剩下的参照kaungbin的板子

#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps = 1e-8;
const db inf = 1e20;
const db pi = acos(-1.0);
int sgn(db x)
{
if (fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct Point
{
db x, y;
Point() {}
Point(db _x, db _y)
{
x = _x;
y = _y;
}
void input()
{
scanf("%lf%lf", &x, &y);
}
bool operator==(Point b) const
{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
Point operator-(const Point &b) const
{
return Point(x - b.x, y - b.y);
}
//叉积
db operator^(const Point &b) const
{
return x * b.y - y * b.x;
}
//点积
db operator*(const Point &b) const
{
return x * b.x + y * b.y;
}
//返回两点的距离
db dis(Point p)
{
return hypot(x - p.x, y - p.y);
}
Point operator+(const Point &b) const
{
return Point(x + b.x, y + b.y);
}
Point operator*(const db &k) const
{
return Point(x * k, y * k);
}
Point operator/(const db &k) const
{
return Point(x / k, y / k);
}
};
struct Line
{
Point s, e;
Line() {}
Line(Point _s, Point _e)
{
s = _s;
e = _e;
}
// 点在线段上的判断
bool pointonseg(Point p)
{
return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s) * (p - e)) <= 0;
}
// 求两直线的交点
Point crosspoint(Line v)
{
double a1 = (v.e - v.s) ^ (s - v.s);
double a2 = (v.e - v.s) ^ (e - v.s);
return Point((s.x * a2 - e.x * a1) / (a2 - a1), (s.y * a2 - e.y * a1) / (a2 - a1));
}
};
// 求点a和点b的中点
Point get_mid(Point a, Point b)
{
return (a + b) * 0.5;
}
int main()
{
int cass;
for (scanf("%d", &cass); cass; cass--)
{
Point a, b, c, p;
Line ab, bc, ac;
a.input(), b.input(), c.input(), p.input();
ab = Line(a, b);
bc = Line(b, c);
ac = Line(a, c);
db area = fabs((b - a) ^ (c - a) * 0.5); // 三角形面积
if (ab.pointonseg(p))
{ // 点p在线段ab上
if (a.dis(p) < b.dis(p))
{ // 点p靠近点a,则另一点一定在线段bc上
Point l = c, r = b;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (b - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
else
{ // 点p靠近点b,则另一点一定在线段ac上
Point l = c, r = a;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (a - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
}
else if (bc.pointonseg(p))
{
if (b.dis(p) < c.dis(p))
{
Point l = a, r = c;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (c - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
else
{
Point l = a, r = b;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (b - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
}
else if (ac.pointonseg(p))
{
if (a.dis(p) < c.dis(p))
{
Point l = b, r = c;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (c - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
else
{
Point l = b, r = a;
Point mid = get_mid(l, r);
int times = 1000;
while (times--)
{
mid = get_mid(l, r);
db s = fabs((mid - p) ^ (a - p));
if (sgn(s - area) > 0) l = mid;
else if (sgn(s - area) == 0) break;
else r = mid;
}
printf("%.10lf %.10lf\n", mid.x, mid.y);
}
}
else puts("-1");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】