最新文章

[CF1C]Ancient Berland Circus 题解

[CF1C]Ancient Berland Circus 题解

题目地址:Codeforces:Problem – 1C – Codeforces、洛谷:CF1C Ancient Berland Circus – 洛谷 | 计算机科学教育新生态

题目描述

Nowadays all circuses in Berland have a round arena with diameter 13 meters, but in the past things were different.

In Ancient Berland arenas in circuses were shaped as a regular (equiangular) polygon, the size and the number of angles could vary from one circus to another. In each corner of the arena there was a special pillar, and the rope strung between the pillars marked the arena edges.

Recently the scientists from Berland have discovered the remains of the ancient circus arena. They found only three pillars, the others were destroyed by the time.

You are given the coordinates of these three pillars. Find out what is the smallest area that the arena could have.

题意简述

给你一个正多边形中某三个点的坐标,求符合条件的最小正多边形的面积。保证答案中的正多边形边数不超过100。

输入输出格式

输入格式:
The input file consists of three lines, each of them contains a pair of numbers –– coordinates of the pillar. Any coordinate doesn’t exceed 1000 by absolute value, and is given with at most six digits after decimal point.

输出格式:
Output the smallest possible area of the ancient arena. This number should be accurate to at least 6 digits after the decimal point. It’s guaranteed that the number of angles in the optimal polygon is not larger than 100.

输入输出样例

输入样例#1:

0.000000 0.000000
1.000000 1.000000
0.000000 1.000000

输出样例#1:

1.00000000

题解

给了三个点,正好能构成一个三角形。这个三角形肯定是正多边形的一部分,接下来考虑如何通过三角形内部的信息求出正多边形的信息。
考虑这个三角形的外接圆即是正多边形的外接圆,可以先把外接圆半径通过正弦定理求出来,即$\frac{a}{\sin A} = 2R \Rightarrow R = \frac{a}{2 \sin A}$。
有了外接圆半径后,我们可以求出三条边在外接圆中对着的圆心角,这可以通过余弦定理求出,即$cos \theta_a = \frac{2r^2-a^2}{2r^2} \Rightarrow \theta_a = \arccos(1-\frac{a^2}{2r^2})$。
考虑枚举多边形的边数,从而计算出多边形每条边对的圆心角,通过判断三条边对的圆心角是否是这个多边形圆心角的整数倍即可判断这三个点是否可以是这个正多边形的三个顶点。选择边数最少的正多边形即可求出最小的面积。
面积的求法,考虑把正$n$边形分成以外接圆圆形为顶点的$n$个小三角形,每个三角形的面积是$\frac{1}{2} R^2 \sin\frac{2\pi}{n}$,乘上边数$n$就得到了总面积。

理论上到此为止这个题已经做完了,但是你会发现直接这么写会WA。接下来是我在写的时候踩的坑,仅供读者参考:

  1. 操作中精度误差比较大,EPS设置$10^{-6}$太小,需要调整到$10^{-4}$。
  2. 如果直接利用余弦定理计算圆心角,容易遇到拿去算$\arccos$的值因为精度误差产生越界值,例如$-1$因为精度误差变成了$-1.00000000003$。考虑到三角形中边对的内角一定小于$\pi$,不会产生越界值,可以余弦定理算内角之后,利用内角是圆周角的性质,乘以2算出圆心角。这样做可以避免圆心角计算出一个nan的情况。

作为高考之后写的第一个练手题,这个题实在坑人,写了一下午2333

代码

// Code by KSkun, 2019/6
#include <cstdio>
#include <cmath>

#include <algorithm>

const double EPS = 1e-4;
const double PI = acos(-1);

inline int dcmp(double x) {
    if(fabs(x) < EPS) return 0;
    else return x < 0 ? -1 : 1;
}

struct Vector {
    double x, y;
    Vector operator+(const Vector &rhs) const {
        return Vector {x + rhs.x, y + rhs.y};
    }
    Vector operator-(const Vector &rhs) const {
        return Vector {x - rhs.x, y - rhs.y};
    }
};

inline double dot(Vector a, Vector b) {
    return a.x * b.x + a.y * b.y;
}

inline double length(Vector x) {
    return sqrt(dot(x, x));
}

inline double angle(Vector a, Vector b) {
    return acos(dot(a, b) / length(a) / length(b));
}

typedef Vector Point;

Point a, b, c;

inline bool checkInt(double x) {
    return dcmp(x - round(x)) == 0;
}

int main() {
    scanf("%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y);
    double al = length(b - c), bl = length(a - c), cl = length(a - b),
        r = cl / sin(angle(a - c, b - c)) / 2;
    double aan = acos((bl * bl + cl * cl - al * al) / 2 / bl / cl) * 2, 
        ban = acos((al * al + cl * cl - bl * bl) / 2 / al / cl) * 2,
        can = 2 * PI - aan - ban;
    for(int i = 3; i <= 100; i++) {
        double in = PI * 2 / i, c1 = aan / in, c2 = ban / in, c3 = can / in;
        if(!checkInt(c1) || !checkInt(c2) || !checkInt(c3) || round(c1 + c2 + c3) != i) continue;
        double s = r * r * sin(in) / 2 * i;
        printf("%.8lf", s); break;
    }
    return 0;
}
[工程师死绝的世界C3002]機械の総合病院 翻译及题解

[工程师死绝的世界C3002]機械の総合病院 翻译及题解

机械综合医院

Translation by KSkun

原题:問題「機械の総合病院」 | エンジニアが死滅シタ世界 〜アンドロイドとふたりぼっちで生きろ〜

问题描述

你在分析PAIZA医院的系统。
为了避免被非法入侵,医院系统的用户密码应该达到一定的强度。
PAIZA医院的系统要求用户密码满足以下的强度要求:

  • 长度不低于6
  • 必须包含英文字母和数字
  • 同一字符不得连续出现3次或以上

密码中,不区分英文字符的大小写。
如果密码满足以上强度要求,输出Valid,否则输出Invalid

例如,样例1中的密码7Caaad9满足条件1和2,但是不满足条件3,因为aaa这里连续出现了3个a字符。

输入格式

t
  • 给出表示密码的字符串t。
  • 在输入的最后,包含一个换行符。

输出格式

如果密码满足以上强度要求,输出Valid,否则输出Invalid

条件

  • 1 ≦ t的长度 ≦ 30
  • 字符串t只包含半角英文字符及半角数字

输入输出样例

输入输出样例1

输入:

7Caaad9

输出:

Invalid

输入输出样例2

输入:

DjZGrduN8Mj4

输出:

Valid

题解

// Code by KSkun, 2019/1
#include <cstdio>
#include <cctype>
#include <cstring>

#include <algorithm>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
        ? EOF : *p1++;
}

inline LL readint() {
    LL res = 0, neg = 1; char c = fgc();
    for(; !isdigit(c); c = fgc()) if(c == '-') neg = -1;
    for(; isdigit(c); c = fgc()) res = res * 10 + c - '0';
    return res * neg;
}

inline char readsingle() {
    char c;
    while(!isgraph(c = fgc())) {}
    return c;
}

char t[35];
bool hasalpha = false, hasdigit = false;

int main() {
    scanf("%s", t + 1);
    int n = strlen(t + 1);
    if(n < 6) {
        puts("Invalid"); return 0;
    }
    int cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(isupper(t[i])) t[i] = tolower(t[i]);
        if(isalpha(t[i])) hasalpha = true;
        if(isdigit(t[i])) hasdigit = true;
        if(t[i] != t[i - 1]) cnt = 1;
        else cnt++;
        if(cnt >= 3) {
            puts("Invalid"); return 0;
        }
    }
    if(!hasalpha || !hasdigit) {
        puts("Invalid"); return 0;
    }
    puts("Valid");
    return 0;
}
[工程师死绝的世界B2002]砂漠の公園 翻译及题解

[工程师死绝的世界B2002]砂漠の公園 翻译及题解

沙漠公园

Translation by KSkun

原题:問題「砂漠の公園」 | エンジニアが死滅シタ世界 〜アンドロイドとふたりぼっちで生きろ〜

问题描述

以前公园经常举行某种比赛的大会。每次比赛的结果记录都能找到,但是哪只队伍最终获得优胜的记录却丢失了。
因此你需要写一个程序来计算最终是哪只队伍获得了优胜。

大会进行循环比赛,按照以下的方式计算每只队伍的得分。一次比赛获胜得2分,平局得1分,输局得0分。
在所有比赛进行完毕后,得分最多的队伍获得优胜。

输入中包含大会的参赛人数以及比赛结果,请设计程序输出比赛的获胜者以及得分和胜利、平局、失败的场数。

样例1解释如下图所示。

botchi b 2002 img - [工程师死绝的世界B2002]砂漠の公園 翻译及题解

输入格式

N
c_{1,1}c_{1,2}...c_{1,N}
c_{2,1}c_{2,2}...c_{2,N}
...
c_{N,1}c_{N,2}...c_{N,N}
  • 第一行包含一个整数N,表示参赛的人数。
  • 接下来的N行中,每行包含N个字符,第i行的第j个字符c_{i, j}表示队伍i和队伍j的比赛结果。
    c_{i, j}的取值的意义如下:
    • 队伍i胜过队伍j时,值为W
    • 队伍i与队伍j打成平局时,值为D
    • 队伍i被队伍j打败时,值为L
    • i = j时,值为-
  • 接下来的N行中,第i行给出第i个需要合并的单词字符串w_i。
  • 输入共N + 1行,在输入的最后,包含一个换行符。

输出格式

你需要输出优胜队伍的编号s、得分t、获胜场数W、平局场数D、失败场数L。

s t W D L
  • 只需要输出1行。
  • 在输出的最后,需要包含一个换行符。

条件

  • 2 ≦ N ≦ 100
  • 1 ≦ i ≦ N
  • 1 ≦ j ≦ N
  • c_{i, j}的取值只可能是WDL-四种
  • c_{i, j}为W时,c_{j, i}为L
  • c_{i, j}为D时,c_{j, i}为D
  • i = j时,c_{i, j}为-
  • 优胜队伍只可能有1支(得分最大的队伍只可能有1支)

输入输出样例

输入输出样例1

输入:

3 
-DW
D-D
LD-

输出:

1 3 1 1 0

输入输出样例2

输入:

10 
-WLDWWDWWW
L-WDWWWLWW
WL-LWWLWWD 
DDW-WWDWWW 
LLLL-LLLWW 
LLLLW-WLLL 
DLWDWL-WLW 
LWLLWWL-WW 
LLLLLWWL-W 
LLDLLWLLL-

输出:

4 15 6 3 0

题解

// Code by KSkun, 2019/5
#include <cstdio>
#include <cctype>
#include <cstring>

#include <algorithm>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
        ? EOF : *p1++;
}

inline LL readint() {
    LL res = 0, neg = 1; char c = fgc();
    for(; !isdigit(c); c = fgc()) if(c == '-') neg = -1;
    for(; isdigit(c); c = fgc()) res = res * 10 + c - '0';
    return res * neg;
}

inline char readsingle() {
    char c;
    while(!isgraph(c = fgc())) {}
    return c;
}

inline bool isop(char c) {
    return c == '-' || c == 'D' || c == 'W' || c == 'L';
}

inline char readop() {
    char c;
    while(!isop(c = fgc())) {}
    return c;
}

const int MAXN = 105;

int n, t[MAXN], w[MAXN], d[MAXN], l[MAXN];

int main() {
    n = readint();
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            char op = readop();
            if(i == j) continue;
            if(op == 'W') {
                w[i]++; t[i] += 2;
            } else if(op == 'D') {
                d[i]++; t[i] += 1;
            } else if(op == 'L') {
                l[i]++;
            }
        }
    }
    int win = 0;
    for(int i = 1; i <= n; i++) {
        if(t[i] > t[win]) win = i;
    }
    printf("%d %d %d %d %d", win, t[win], w[win], d[win], l[win]);
    return 0;
}