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

被折叠的 条评论
为什么被折叠?



