Extra Training Contest 3

本文总结了几道编程竞赛题目,包括使用泊松定理解决的外星人器官问题、采用贪心算法的达喀尔拉力赛加油策略、通过公式推导解决的吉波纳奇数列问题以及结合01背包问题和路径记录的快乐编程竞赛问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

陆续的把最近几场比赛写一写,怕不写又忘了,在补一补没做的题。

A - Alien's Organ ZOJ - 3696 (泊松定理)

刚学过去几天,打比赛时就忘了,被欣姐一顿鄙视,嘤嘤嘤

公式题直接贴代码吧:

#include<bits/stdc++.h>
using namespace std;

int t, n;
double f;
double qf(int k)
{
    if(k == 0) return 1;
    return k *(qf(k - 1));
}
double get(int k)
{
    return pow(f, k) / qf(k);
}
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%lf", &n, &f);
        double ans = pow(exp(1), -f);
        double sum = 1;
        for(int i = 1; i <= n; i++)
            sum += get(i);
        sum *= ans;
        printf("%.3lf\n", sum);
    }
    return 0;
}

D - Dakar Rally ZOJ - 3699(贪心)

题意:开车行驶,油箱容积一定,只能在特定的点加油,然后让你找到最省钱的加油方式。

1.如果某条路线用的油大于了油箱容积,则不合题意。

2.如果可以找到加油点更便宜或者不用加满就可以到终点的就只需加到所需容积。

3.如果不能则加满。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;

int T, m, v, mil, c, a[maxn], p[maxn];
int main()
{
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &m, &v);
        int flag = 0;
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &mil, &c, &p[i]);
            a[i] = mil * c;
            if(a[i] > v) flag = 1; // 油箱容积不满足
        }

        if(flag) printf("Impossible\n");
        else
        {
            int i, j;
            long long ans, res, t1;
            res = ans = 0; i = j = 0;
            while(i < m) // 是否到达终点
            {
                j = i + 1, t1 = a[i];
                while(j < m && p[i] <= p[j] && v - t1 >= a[j]) // 看是否有更便宜的下个地点
                {
                    t1 += a[j];
                    j++;
                }
                if(j >= m || p[j] < p[i]) // 到终点或者到达更偏的点
                {
                    if(res >= t1) res -= t1;
                    else
                    {
                        ans = ans + (long long)(t1 - res) * p[i];
                        res = 0;
                    }
                    i = j;
                }
                else // 油箱加满
                {

                    ans = ans + (long long)(v - res) * p[i];
                    res = v - a[i];
                    i++;
                }
            }
            printf("%lld\n", ans);
        }

    }
    return 0;
}

G - Gibonacci number ZOJ - 3702(公式推导)

简单的公式推到题,推一推系数项好像可以跟斐波那契数列联系上,但我用了更加朴素的方法,直接记录了常数项和系数项。打表求出。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000100;

int t, i, G, j;
pair<long long, long long> P[maxn];
void init()
{
    P[0].first = 0, P[0].second = 1;
    P[1].first = 1, P[1].second = 0;
    for(int i = 2; i < maxn; i++)
    {
        P[i].first = P[i - 1].first + P[i - 2].first;
        P[i].second = P[i - 1].second + P[i - 2].second;
    }
}

int main()
{
    init();
    scanf("%d", &t);
    while(t--)
    {
       scanf("%d%d%d", &i, &G, &j);
       long long re;
       re = (G - P[i].second) / P[i].first;

       if(re < 1 || re * P[i].first + P[i].second != G)
       {
           printf("-1\n");
       }
       else
       {
           printf("%lld\n", P[j].first * re + P[j].second);
       }
    }
    return 0;
}

H - Happy Programming Contest ZOJ - 3703(01背包+记录路径)

题意:一男生带妹打比赛。然后每道题都有让妹子的最大开心值不同,然后需要在得到最大的妹子开心值的前提下,保证做题量尽量的多且罚时尽量的少。

和普通的01背包不同的一点是这道题要进行路径的记录。对于路径的记录则是要另开一个数组进行记录,如果在dp过程中路径发生了改变,则进行一次记录,最后在查找的时候再进行一遍回溯就可以了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;

int T, t1, n, t[maxn], v[maxn], dp[maxn];
int num[maxn], book[maxn][maxn];
int main()
{
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &t1, &n);
        for(int i = 1; i <= n; i++) scanf("%d", &t[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &v[i]);

        memset(dp, 0, sizeof(dp));
        memset(book, 0, sizeof(book));
        for(int i = 1; i <= n; i++)
            for(int j = t1; j >= t[i]; j--)
        {
            if(dp[j] < dp[j - t[i]] + v[i])
            {
                dp[j] = dp[j - t[i]] + v[i];
                book[i][j] = 1;
            }
        }
        int j = t1, k = 0, sum = 0, num1 = 0;
        for(int i = n; i >= 1; i--)
        {
            if(book[i][j]){
                num[++k] = t[i];
                j -= t[i];
            }
        }
        sort(num + 1, num + k + 1);
        for(int i = 1; i <= k; i++)
        {
            num1 += num[i];
            sum = sum + num1;
        }
        printf("%d %d %d\n", dp[t1], k, sum);
    }

    return 0;
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值