题目链接:点这里
A.Briefcases Full of Money
- 题意
分别对应数量的面值币,请你选择总和金额最大的币的面值。如果存在相同的,输出面值最大的。
-
解题思路
水题,直接取出最大值即可。 -
AC代码
/**
*@filename:A
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-21 21:07
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int a[7],b[7] = {0,1,5,10,20,50,100};
void solve(){
int maxx = a[1], pos = 1;
for(int i = 2; i <= 6; ++ i){
if(a[i] >= maxx){
maxx = a[i];
pos = i;
}
}
cout << b[pos] << endl;
}
int main(){
for(int i = 1; i <= 6; ++ i){
cin >> a[i];
a[i] *= b[i];
}
solve();
return 0;
}
B.A Game Called Mind
-
题意
有 p p p个玩家,每个玩家有 c i c_i ci张卡片,分别有一个权值,按权值排列输出拥有这张卡片的玩家。 -
解题思路
利用pair对,first存储卡片权值,second存储拥有这张卡片的玩家序号,排序即可。 -
AC代码
/**
*@filename:B
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-21 21:14
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int p,c,x;
vector<pair<int,int> > v;
void solve(){
sort(v.begin(), v.end());
for(auto &iter : v){
cout << (char)(iter.second + 'A');
}
cout << endl;
}
int main(){
cin >> p;
for(int i = 0; i < p; ++ i){
cin >> c;
for(int j = 0; j < c; ++ j){
cin >> x;
v.push_back({x,i});
}
}
solve();
return 0;
}
C.Unique Values
-
题意
给你一个序列,需要你计算出所有连续子序列中没有出现重复元素的总序列个数。 -
解题思路
首先我们知道,对于一个未出现重复元素的序列,其真子序列必定也是扶额和要求的,所以我们如果找到了一个最长的未出现重复元素的序列,那么其方案我们可以记作其长度,从而不用考虑它的子序列了。 所以,我们可以利用双指针,去寻找这符合要求的最长子序列,为了判断是否出现重复元素,我们利用hasSet可以实现,记得在指针移动过程中需要及时插入新元素和剔除过期元素即可。 -
AC代码
/**
*@filename:C
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-21 21:24
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int n;
ll a[N];
unordered_set<ll> t;//set存放。
void solve(){
ll ans = 0;
int l = 1, r = 1;
while(l <= r){
while(r <= n && !t.count(a[r])){
t.insert(a[r]);
r ++;
}
ans += r - l;
t.erase(a[l]);
l ++;
}
cout << ans << endl;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
}
solve();
return 0;
}
D.Gone Fishing
-
题意
给你一个可以移动的半径为 r r r的圆和 n n n个点,需要你判断出该圆最多可以覆盖多少个点。 -
解题思路
按照贪心原则,为了极大的覆盖区域,我们必定会选择两个点在圆上,这样就可以唯一确定一个圆。所以我们可以枚举这两个点,从而计算出圆心的位置。最后统计符合要求的最大点数即可。 -
解题思路
/**
*@filename:D
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-22 18:49
**/
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<double,double> pdd;
const int N = 100000 + 5;
const double EPS = 1e-8;
const int P = 1e9+7;
double r;
int n;
pdd points[110];
double getDist(pdd a,pdd b){
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
pdd getCenter(pdd a, pdd b){
pdd mid = {(a.x + b.x) / 2, (a.y + b.y) / 2};
double w = atan2(a.x - b.x,b.y - a.y);//计算正切值。
double d = sqrt(r * r - getDist(a,mid) * getDist(a,mid));
return {mid.x + d * cos(w),mid.y + d * sin(w)};
}
void solve(){
int maxx = 1;
for(int i = 1; i <= n; ++ i){
for(int j = i + 1; j <= n; ++ j){
if(getDist(points[i],points[j]) > 2 * r)continue;
pdd cen = getCenter(points[i],points[j]);
int cnt = 0;
for(int k = 1; k <= n; ++ k){
if(getDist(points[k],cen) < r + EPS)cnt ++;//注意精度问题,在计算过程中可能会损失精度,我们需要加上一个精度控制。
}
maxx = max(cnt,maxx);
}
}
cout << maxx << endl;
}
int main(){
cin >> r;
cin >> n;
for(int i = 1; i <= n; ++ i){
cin >> points[i].x >> points[i].y;
}
solve();
return 0;
}
E.Sum of a Function
-
题意
定义函数 F ( x ) F(x) F(x)为 x x x的最小素因子,给定一个区间 [ l , r ] [l,r] [l,r],求出其中前 k k k小的 F ( x ) F(x) F(x)总和。 -
解题思路
看到这个题,注意到 l , r l,r l,r的数据范围,如果我们直接筛素数,是不可能实现的。这道题和 P O J POJ POJ上的Prime Distance题目很像,都是利用偏移,通过剔除素数因子来实现的。我们知道由于 k k k是只占区间的 90 % 90\% 90%,而 2 n , 3 n , 5 n , 7 n . . . 2n,3n,5n,7n... 2n,3n,5n,7n...我们通过素数因子筛掉的数就足足有 90 % 90\% 90%。所以我们的思路是直接筛出 1 e 6 1e6 1e6以内的素数。然后通过筛出的素数,去确定其区间中的数的最小素数因子即可,注意区间偏移。 -
AC代码
/**
*@filename:E
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-22 10:55
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000000 + 5;
const int P = 1e9+7;
bool notPrimer[N];
int primer[N];
ll l,r,k,res[N];
void init(){
for(int i = 2; i < N; ++ i){
if(!notPrimer[i]){
primer[++ primer[0]] = i;
}
for(int j = 1; j <= primer[0] && i * primer[j] < N; ++ j){
notPrimer[i * primer[j]] = true;
if(i % primer[j] == 0)break;//说明碰到了素因子,直接退出。
}
}
}
void solve(){
init();
for(int i = 0; i < r - l + 1; ++ i){
res[i] = l + i;//平移区间。
}
for(int i = 1; i <= primer[0]; ++ i){
if(primer[i] >= r)break;
ll temp1 = (l - 1) / primer[i] + 1;
if(temp1 == 1)temp1 = 2;
ll temp2 = r / primer[i];
for(ll j = temp1; j <= temp2 && j * primer[i] <= r; ++ j){
if(res[j * primer[i] - l] == j * primer[i]){
res[j * primer[i] - l] = primer[i];
//cout << j * primer[i] << " " << primer[i] << endl;
//cout << primer[i] << " ";
}
}
}
sort(res,res + r - l + 1);
ll sum = 0;
for(int i = 0; i < k; ++ i){
sum += res[i];
}
cout << sum << endl;
}
int main(){
cin >> l >> r >> k;
solve();
return 0;
}
F.Hang Gliding
-
解题思路
给你一系列任务的信息,现在需要你确定每个玩家能获得的最大分数。 -
解题思路
由于每个玩家都是互相独立的,所以我们可以分开计算。对于每个玩家,这个任务可以做或者不做,这类似于背包问题,如果做了这个任务,那么这段时间内就不可以做别的任务;如果没有做这个任务,那么最大分数就和上个状态一样。我们来确定一下状态,设 d p [ j ] dp[j] dp[j]为遍历到第 j j j个任务的最大分数,那么 d p [ j ] = m a x ( d p [ j − 1 ] , d p [ 第 j 个 任 务 开 始 前 最 晚 完 成 的 任 务 ] + s c o r e [ j ] dp[j] = max(dp[j - 1],dp[第j个任务开始前最晚完成的任务] + score[j] dp[j]=max(dp[j−1],dp[第j个任务开始前最晚完成的任务]+score[j]。据此,则可以解决。注意纪录任务的下标。还有一个值得注意的点,这种任务序列,决定其的永远是结束时间,而不是开始时间。 -
AC代码
/**
*@filename:F
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-22 19:39
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10000 + 5;
const int P = 1e9+7;
int n,m;//飞行员数量和任务数。
struct node{
double st,ed,score;
int pos;
bool operator < (node A){
if(ed == A.ed){
return st < A.st;
}
return ed < A.ed;
}
}tasks[N];
double stu[110][N];
double score[110][N];
struct node1{
double score;
int pos;
bool operator < (const node1 A){
return score > A.score;
}
}result[N];
int cal(int r, double x){
int l = 1;
while(l <= r){
int mid = (l + r) >> 1;
//cout << "l:" << l << " r:" << r << endl;
if(tasks[mid].ed <= x){
l = mid + 1;
}
else{
r = mid - 1;
}
}
return r;
}
void solve(){
sort(tasks + 1, tasks + 1 + m);
for(int i = 1; i <= n; ++ i){
double maxx = 0;
for(int j = 1; j <= m; ++ j){
score[i][tasks[j].pos] = max(score[i][tasks[j - 1].pos], score[i][tasks[cal(j - 1,tasks[j].st)].pos] + stu[i][tasks[j].pos]);
maxx = max(maxx, score[i][tasks[j].pos]);
}
result[i].score = maxx;
result[i].pos = i;
}
sort(result + 1, result + 1 + n);
for(int i = 1; i <= 3; ++ i){
printf("%d %.2lf\n", result[i].pos, result[i].score);
}
}
int main(){
scanf("%d%d", &m, &n);
for(int i = 1; i <= m; ++ i){
scanf("%lf%lf%lf", &tasks[i].st, &tasks[i].ed, &tasks[i].score);
tasks[i].pos = i;
}
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
scanf("%lf", &stu[i][j]);
stu[i][j] *= tasks[j].score;
}
}
solve();
return 0;
}