The 2019 ICPC Asia Nanjing Regional Contest

Hanser·2022-01-08 18:50·222 次阅读

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;
}
View Code
复制代码

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;
}
View Code
复制代码

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;
}
View Code
复制代码

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;
}
View Code
复制代码

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;
}
View Code
复制代码
posted @   ゼロツー  阅读(222)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Live2D Title
欢迎阅读『The 2019 ICPC Asia Nanjing Regional Contest』
点击右上角即可分享
微信分享提示