题目链接

A L1-1小乐乐是否被叫家长

简单,没什么说的,但是要注意尽量不要使用小数去运算,转化成正整数运算不会出现精度问题

#include<iostream>

using namespace std;

int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    int sum=a+b+c;
    if(sum>=180)puts("NO");
    else puts("YES");
    return 0;
}

B L1-2你要乘坐的飞碟在这里

就是简单的把字符串转化成数字比较一下,比赛脑子瓦特了,搞了半天

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    string s1, s2;
    cin >> s1 >> s2;
    long long ans1 = 1, ans2 = 1;
    for (int i = 0; i < s1.size(); i++)ans1 *= (s1[i] - 'A' + 1);
    for (int i = 0; i < s2.size(); i++)ans2 *= (s2[i] - 'A' + 1);
    //cout<<ans1<<' '<<ans2<<endl;
    if ((ans1 % 47) == (ans2 % 47))puts("GO");
    else puts("STAY");
    //cout<<'A'-'A'<<endl;
    return 0;
}

C L1-3成绩

仔细读题就好了

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int a, b, c;
    cin >> a >> b >> c;
    cout << a * 0.2 + b * 0.3 + c * 0.5;
    return 0;
}

D L1-4素数分布

打表找素数,学习一下素数的几种筛法

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        long long cnt = 0;
        for (int i = 2; i  <= n; i++) {
            bool flag = true;
            for (int j = 2; j < i; j++) {
                if (i % j == 0){
                    flag = false;
                    break;
                }
            }
            if (flag)cnt++;
        }
        cout << cnt << endl;
    }
    return 0;
}

E L1-5便便传送门(一)

把所有可能出现的情况考虑进去就好了,贪心,距离近的痛拖拉机,距离远的用传送门,注意a,b的相对大小不确定。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int a, b, x, y;
    cin >> a >> b >> x >> y;
    if(a>b)swap(a,b);
    int dis = 0;
    dis += abs(a - min(x, y));
    dis += abs(b - max(x, y));
    if(dis<abs(a-b))cout << dis << endl;
    else cout<<abs(a-b)<<endl;
    return 0;
}

F L1-6有序序列插入一个数

这题是相当简单了,直接读入所有数,排个序即可。

看看我愚蠢的做法,我要被蠢哭了

#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long

using namespace std;

const int N = 100010;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin >> n;
    int a[n + 10];
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    int y;
    cin >> y;
    int ret = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] > y && ret == 0)cout << y << ' ', ret = 1;
        cout << a[i] << ' ';
    }
    if(ret==0)cout<<y<<' ';
    return 0;
}

直接读入排序它不香

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int a[55];
int n;

int main()
{
    cin>>n;
    for(int i=0;i<=n;i++)cin>>a[i];
    sort(a,a+n+1);
    for(int i=0;i<=n;i++)cout<<a[i]<<' ';
    return 0;
}

G L1-7货物收集

这个题就是关于图论的题,它的意思就是尽量耗费少的代价会获得目标货物和,可以看成最短路径的问题,可以用迪杰斯特拉来做,也可以直接用bfs来做,一层一层的扩展,还可以使用dfs+二分来做。

bfs(使用优先队列来实现)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

typedef pair<int,int> PII;

const int N = 1000010;

int n, W;
int va[N];  //货物储备
int e[N], ne[N], h[N], idx, w[N];  //w为所要消耗的体力
bool vis[N];

void add(int x,int y, int c) {
    e[idx] = y, w[idx] = c, ne[idx] = h[x], h[x] = idx++;
}

int main() {
    memset(h, -1, sizeof h);
    cin >> n >> W;
    for (int i = 2; i <= n; i++)cin >> va[i];
    for (int i = 1; i < n; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
//    for (int i = 1; i <= n; i++) {
//        cout << i << ':';
//        for (int j = h[i]; j != -1; j = ne[j]) {
//            cout << e[j] << '|' << w[j] << ' ';
//        }
//        puts("");
//    }
    va[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> q;
    int sum = 0;
    int ans = 0;
    q.push({0, 1});
    while (q.size()) {
        auto t = q.top();
        q.pop();
        ans = max(ans, t.first);
        sum += va[t.second];
        if (sum >= W)break;
        for (int i = h[t.second]; i != -1; i = ne[i]) {
            if (!vis[e[i]]) {
                vis[e[i]] = true;
                q.push({w[i], e[i]});
            }
        }
    }
    cout << ans << endl;
    return 0;
}

迪杰斯特拉算法求最短路

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

#define PII pair<int,int>
#define f first
#define s second

using namespace std;

const int N = 150010, INF = 0x3f3f3f3f;

int n, m;
int h[N], e[N], w[N], ne[N], idx;
bool vis[N];
int dis[N];
int val[N];
int sum;

void add(int x,int y,int z) {
    e[idx] = y, w[idx] = z, ne[idx] = h[x], h[x] = idx++;
}

int dijkstra() {
    memset(dis, 0x3f, sizeof dis);
    dis[1] = 0;
    priority_queue<PII, vector<PII >, greater<PII>> heap;
    heap.push({0, 1});
    while (heap.size()) {
        auto t = heap.top();
        heap.pop();
        if (vis[t.s])continue;
        vis[t.s] = true;
        sum += val[t.s];
        if (sum >= m)return dis[t.s];
        for (int i = h[t.s]; i != -1; i = ne[i]) {
            if (dis[e[i]] > max(dis[t.s], w[i])) {
                dis[e[i]] = max(dis[t.s], w[i]);
                heap.push({dis[e[i]], e[i]});
            }
        }
    }
    if (dis[n] == INF)return -1;
    return dis[n];
}

int main() {
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for(int i=2;i<=n;i++)cin>>val[i];
    for(int i=1;i<n;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    cout << dijkstra() << endl;
    return 0;
}

H L1-8道路铺设

这个题不知道为什么,考试愣是没想起来,所以考试写了个递归最后超时只拿到了80%的分数,可以用dfs来做,但是正解应该是,从第一个开始遍历,如果后面的一个比它大,就对这个没有贡献,填这个会把下一个也填平,如果后面的更大就填不平,还需要用后一个减去前一个的插值才可以填平。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010;

int n;
int a[N];

int main() {
    cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; i++)cin >> a[i];
    sum += a[1];
    for (int i = 2; i <= n; i++) {
        if (a[i] > a[i - 1])sum += a[i] - a[i - 1];
    }
    cout << sum << endl;
    return 0;
}

dfs

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;

const int N = 100010;

int n;
int a[N];
int res;

void dfs(int l,int r) {
    int Min=100000010;
    for (int i = l; i <= r; i++)Min = min(Min, a[i]);
    for (int i = l; i <= r; i++)a[i] -= Min;
    res += Min;
    int pos = -1;
    for (int i = l; i <= r; i++) {
        if (pos == -1 && a[i] > 0)pos = i;
        else if (pos != -1 && a[i] == 0) {
            dfs(pos, i-1);
            pos = -1;
        }
    }
    if (pos != -1)dfs(pos, r);
    return ;
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)cin >> a[i];
    dfs(1, n);
    cout << res << endl;
    return 0;
}

I L2-1货币系统

这个就是一个裸完全背包问题,抽象一下就是前面小的能不能凑成后面大的,如果能,后面的就是多余的,不需要的,所以就变成了先用完全背包,把能凑出来的标记一下,如果是用这个去凑,这个就不能标记,最后统计,如果给出的面值被标记了,那就是不需要的。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 110, M = 25010;

int n;
int a[N];
int f[M];
bool vis[M];

int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> n;
        int ans=n;
        for (int i = 1; i <= n; i++)cin >> a[i];
        sort(a+1,a+1+n);
        memset(vis,false,sizeof vis);
        memset(f,0,sizeof f);
        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            if (vis[a[i]])continue;
            for (int j = a[i]; j <= 25000; j++) {
                f[j]|=f[j-a[i]];
                if (f[j])vis[j] = true;
            }
            vis[a[i]]=false;
        }
        //for (int k = 1; k <= 30; k++)cout<<vis[k]<<' ';cout<<endl;
        for (int i = 1; i <= n; i++)if (vis[a[i]])ans--;
        cout << ans << endl;
    }
    return 0;
}

J L2-2***

就是一道模拟题,读懂题目意思,耐心点。

#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long

using namespace std;

const int N = 100010;

int l, r;
int n;
int a[N];
int m, p1, s1, s2;

int32_t main() {
    cin >> n;
    for (int i = 1; i <= n; i++)cin >> a[i];
    cin >> m >> p1 >> s1 >> s2;
    for (int i = 1; i < m; i++)l += (m - i) * a[i];
    for (int i = m + 1; i <= n; i++)r += (i - m) * a[i];
    if (p1 > m)r += (p1 - m) * s1;
    else l += (m - p1) * s1;
    int diff = abs(l - r);
    int pos = m;
    for (int i = 1; i <= n; i++) {
        if (i == m)continue;
        else if (i < m) {
            int dif = abs((m - i) * s2 + l - r);
            if (dif < diff)diff = dif, pos = i;
        } else {
            int dif = abs((i - m) * s2 + r - l);
            if (dif < diff)diff = dif, pos = i;
        }
    }
    cout << pos << endl;
    return 0;
}