AtCoder Beginner Contest 145

A - Circle

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int r;
int main(){
    cin >> r;
    cout << r * r << endl;
    return 0;
}

B - Echo

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int n;
string s;
int main() {
    cin >> n >> s;
    if (n & 1)
        cout << "No" << endl;
    else {
        int mid = n / 2;
        for (int i = 0; i < mid; i++) {
            if(s[i]!=s[i+mid]){
                cout << "No" << endl;
                return 0;
            }
        }
        cout << "Yes" << endl;
    }
    return 0;
}

C - Average Length

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int n, base[10];
double x[10], y[10];
int main() {
    for (int i = 1; i <= 8; i++) base[i] = i;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> x[i] >> y[i];
    double sum = 0;
    int cnt = 0;
    while (1) {
        double tmp = 0;
        for (int i = 2; i <= n; i++) {
            tmp += sqrt((x[base[i]] - x[base[i-1]]) * (x[base[i]] - x[base[i-1]]) +
                        (y[base[i]] - y[base[i-1]]) * (y[base[i]] - y[base[i-1]]));
        }
        sum += tmp;
        cnt++;
        if (!next_permutation(base+1,base+n+1)) break;
    }
    printf("%.7lf
", sum / (double)cnt);
    return 0;
}

D - Knight

大意:

一个棋子从原点开始,当坐标为xy时,可以跳到(x+2,y+1)或者(x+1,y+2)

给出一个坐标(n,m),问有多少种方法可以走到这个点

思路:

首先考虑点(n,2 * n),那么只有一个方法可以走到

而对于点(n+1,2 * n-1),有n个方法可以走到,也就是任选一个横着跳的,把它改成竖着跳的

以此类推,组合计数一顿乱搞即可

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int n, m;
LL res, mod = 1e9 + 7;

int fact[N], infact[N];

LL qmi(LL a, LL k, LL p) {
    LL res = 1;
    while (k) {
        if (k & 1) res = res * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return res;
}

// 预处理
void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; ++i) {
        fact[i] = (LL)fact[i - 1] * i % mod;
        infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
}

LL Cnm(int a,int b){
    return (LL)fact[a] * infact[b] % mod * infact[a - b] % mod;
}
int main() {
    cin >> n >> m;
    init();
    for (int i = 0; i <= min(n, m); i++) {
        if(2*n-3*i==m){
            res = (res + Cnm(n-i, i))%mod;
        }
    }
    cout << res << endl;
    return 0;
}

E - All-you-can-eat

大意:

有n道菜,每道菜需要a[i]分吃完,能获得b[i]的美味值 给T分钟,问怎么样吃,才能在T内得到最多的美味值,

一旦开始了吃就一定会吃完这道菜,哪怕时间超过T分

思路:

之前背包的上限容量 是T,但是因为题目限制,所以可以把背包容量扩充到 T+w[i]-1

这个时候这个物品就可以超出 容量T ,并且小于 T+w[i] 也保证了不可能出现大于容量T还进行的情况。

但是还有一个点是要对物品进行排序,先选时间小的

可以考虑一个极端的情况来理解:如果一个物品时间非常大,大于T,如果先考虑用它进行背包,那么后面小的物品更新的时候肯定不会考虑到这个物品,但是如果最后才考虑这个物品,可以最后吃它,然后超过t仍然可以吃

#include <bits/stdc++.h>

using namespace std;

const int N = 1e4 + 5;
typedef long long LL;
int n, t;

LL dp[N];
struct node {
    LL x, v;
} a[N];
bool cmp(node a, node b) { return a.x < b.x; }
int main() {
    cin >> n >> t;
    LL res = 0;
    for (int i = 0; i < n; i++) cin >> a[i].x >> a[i].v;
    //sort(a, a + n, cmp);
    for (int i = 0; i < n; i++) {
        for (int j = t + a[i].x - 1; j >= a[i].x; j--) {
            dp[j] = max(dp[j], dp[j - a[i].x] + a[i].v);
            res = max(res, dp[j]);
        }
    }
    cout << res << endl;
    return 0;
}

F - Laminate

大意:

现在有n个柱子排在一起,每个柱子有个高度hi。
现在有至多k次机会任意修改某些柱子的高度。
之后会执行操作:每次可以横向消去一段连续的柱子。问最终最少的操作次数是多少。

思路:

抄的https://blog.csdn.net/qq_43857314/article/details/103441434

太难想了orz...

图片.png

原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14438285.html