2021“MINIEYE杯”中国大学生算法设计超级联赛(2)

本文解析了两道算法竞赛题目,包括类背包动态规划问题和数学构造问题。第一题要求通过优化复习策略来最大化总分;第二题则涉及计算特定序列的逆序对数量。

2021“MINIEYE杯”中国大学生算法设计超级联赛(2)

1008 I love exam (类背包DP)

描述
有t天时间复习,n种课程,m个复习资料,每个资料i可以花费yi天让一种课程
增加xi分,60分及格,满分100分,刚开始每门课程都只能考0分,最多可以允许你有p个课程不及格,求在满足要求的情况下所有课程能获得的最大总分。

题目链接


分析
在这里插入图片描述
代码

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define Min(a,b,c)  min(a,min(b,c))
#define Max(a,b,c)  max(a,max(b,c))

typedef long long ll;
typedef unsigned long long ull;

const double pi = 3.141592653589793;
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;

const int N = 60, M = 15010, X = 20, Y = 20, T = 510, P = 5;


int n, m, t, p;
int f[N][120], mx[N][T], dp[T][P];
map<string, int> mp;
vector<pii> vec[N];


int main()
{
    int tt;
    scanf("%d", &tt);
    while (tt--)
    {
        scanf("%d", &n);
        char s[20];
        
        for (int i = 1; i <= n; i++)
        {
            scanf("%s", s);
            mp[s] = i;
        }
        scanf("%d", &m);
        for (int i = 1; i <= m; i++)
        {
            int x, y;
            scanf("%s%d%d", s, &x, &y);
            vec[mp[s]].push_back({x, y});
        }
        scanf("%d%d", &t, &p);
        memset(f, 0x3f, sizeof(f));
        memset(mx, 0, sizeof(mx));
        memset(dp, -0x3f, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            f[i][0] = 0;
            for (int j = 0; j < vec[i].size(); j++)
                for (int k = 110; k >= vec[i][j].fi; k--)
                    f[i][k] = min(f[i][k], f[i][k - vec[i][j].fi] + vec[i][j].se);
            for (int k = 110; k >= 100; k--)   
                f[i][k] = min(f[i][k], f[i][k + 1]);
            for (int k = 1; k <= 100; k++)
                if (f[i][k] <= 500)
                    mx[i][f[i][k]] = max(mx[i][f[i][k]], k);
        }
        dp[0][0] = 0;
        for (int i = 1; i <= n; i++)
        {
            for (int j = t; j >= 1; j--)
            {
                for (int k = p; k > 0; k--) dp[j][k] = dp[j][k - 1];
                dp[j][0] = -INF;
                for (int k = 0; k <= p; k++)
                    for (int l = 1; l <= f[i][100] && l <= j; l++)
                        if(mx[i][l] >= 60) dp[j][k] = max(dp[j-l][k] + mx[i][l], dp[j][k]);
    	    	        else if(k) dp[j][k] = max(dp[j - l][k - 1] + mx[i][l], dp[j][k]);
            }
            dp[0][0] = -INF;
        }
        int ans = -1;
        for (int i = 1; i <= t; i++)
            for (int j = 0; j <= p; j++)
                ans = max(ans, dp[i][j]);
        printf("%d\n", ans);
        mp.clear();
        for (int i = 1; i <= n; i++) vec[i].clear();
    }
    return 0;
}


1010 I love permutation (数学构造,剩余系)

题目描述
有奇素数P和小于P的一个正整数a,构建一个长度为P-1的序列b , 其中bx = x*a % P ( 1 <= x <= p - 1) 。求序列b中逆序对个数,结果对2取模。

题目链接


分析
在这里插入图片描述
代码

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define Min(a,b,c)  min(a,min(b,c))
#define Max(a,b,c)  max(a,max(b,c))

typedef long long ll;
typedef unsigned long long ull;

const double pi = 3.141592653589793;
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;

ll qmul(ll a, ll b, ll p)
{
    ll c = (long double)a / p * b;
    ll res = (ull)a * b - (ull)c * p;
    return (res + p) % p;
}

ll qmi(ll a, ll b, ll p)
{
    ll ans = 1;
    for (; b; b >>= 1)
    {
        if (b & 1) ans = qmul(ans, a, p);
        a = qmul(a, a, p);
    }
    return ans;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        ll a, p;
        scanf("%lld%lld", &a, &p);
        ll sgn = qmi(a, (p - 1) / 2, p);
        if (sgn == 1) puts("0");
        else puts("1");
    }
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值