文章目录

  • 前言
  • 我的徒弟都是实习生
  • 快穿之我只想测身高
  • 凡人追妹传之大学篇
  • 北宋大烟篓
  • 游戏败家子
  • 超神排位赛
  • 这个大师太过正经
  • 糖果的四十六亿种分法
  • 我有一座研究院
  • 特拉福珠宝俱乐部
  • 吃糖直播间
  • 我师傅实在太稳健了
  • 大奉卖笔人

前言

网络赛有效提交者143人(不包括打星选手),题目类型包括数据结构,模拟,动态规划,贪心等算法

让我们来看看排行前十的选手(没错,打星选手就是大佬,学长闲着做了一下直接AK了…)

本次IT节网络赛由某点倾情赞助…就怪

去年是二次元,今年是网文系列

题目名字改编自以下小说

  • 我的徒弟都是大反派

  • 快穿之xxx系列(这个太多了)

  • 凡人修仙传之仙界篇

  • 北宋大丈夫

  • 明朝败家子

  • 超神机械师

  • 这个人仙太过正经

  • 进化的四十六亿重奏

  • 我有一座冒险屋

  • 手术直播间

  • 特拉福买家俱乐部

  • 我师兄实在太稳健了

  • 大奉打更人

听说有人觉得插图好看,那就找出题人要照片吧,其实有些图片和题目都没啥关系~

下面给出C++代码

没有学习C++的同学,可以简单把cin看成C语言里的scanf,把cout看成C语言里的printf

我们会根据一定比例挑选进入现场赛的选手,届时将会将名单公布,欢迎关注公众号北师珠ACMICPC,敬请期待

我的徒弟都是实习生

简单组合数学问题

有一点点小坑,如果按照正常算的话会溢出(边界数据阶乘unsigned long long都存不下)

坑就在这里,我们需要的是解决溢出问题,不是时间

看着很少有一发过的人,基本都被出题人坑了一手

#include<iostream>using namespace std;
typedef long long ll;
ll cb[100001];//ll C(ll k,ll n){//溢出的做法
//  ll a = n-k,b = k;
//  if(a>b){//保证a最小
//      a^=b^=a^=b;
//  }
//  if(a==0)return 1;
//  ll res = 1;
//  for(int i=n ; i>b ; i--){//      res*=i;
//  }
//  for(int i=2 ; i<=a ; i++){//      res/=i;
//  }
//  return res;
//}ll C(ll k, ll n) {//优化ll a = n - k, b = k;if (a > b) {//保证a最小a ^= b ^= a ^= b;}if (a == 0)return 1;ll res = 1;for (int i = n, j = 1; i > b; i--, j++) {res *= i;if (j <= a) {res /= j;}}return res;
}int main() {ll t, n, m;while (cin >> t >> m >> n) {ll res = 0;for (int i = 4; i <= t - 1; i++) {int man = i;int girl = t - i;if (man <= n && girl <= m) {res += C(man, n) * C(girl, m);}}cout << res << "\n";}
}

快穿之我只想测身高

思考:

题目中的M对关系实际上是人之间身高的相对大小关系。具体来说,我们建立一个数组C,数组中起初全为0。若一条关系指明Ai和Bi可以互相看见(不妨设Ai<Bi),则把数组C中下标为Ai+1到Bi-1的数都减去1,意思是在Ai和Bi中间的人,身高至少要比它们小1。因为第P个人是最高的,所以最终C[p]一定为0。其他的人与第P个人的身高差距就体现在数组C中。换言之,最后第i个人的身高就等于H+C[i]。如果我们朴素执行把数组C中下标为Ai+1到Bi-1的数都减去1的操作,那么整个算法的时间复杂度为O(NM),复杂度过高。一个简单而高效的做法是,额外建立一个数组D,对于每对A和B,令D[Ai+1]减去1,D[Bi]加上1。其含义是:“身高减小1”的影响从Ai+1开始,持续到Bi-1,在Bi结束。最后,C就等于D的前缀和。

上述优化后的算法把对一个区间的操作转化为左、右两个端点上的操作,再通过前缀和得到原问题的解。这种思想很常用,我们在后面还会多次遇到。该算法的时间复杂度为O(N+M)。
另外,在本题的数据中,一条关系(A,B)可能会输入多次,要注意检查,对于重复的关系,只在第一次出现时执行相关操作即可。这一点需注意

#include<bits/stdc++.h>using namespace std;
map<pair<int, int>, bool> existed;
int c[10010], d[10010];int main() {int n, p, h, m;cin >> n >> p >> h >> m;for (int i = 1; i <= m; i++) {int a, b;scanf("%d%d", &a, &b);if (a > b) swap(a, b);if (existed[make_pair(a, b)]) continue;d[a + 1]--;d[b]++;existed[make_pair(a, b)] = true;}for (int i = 1; i <= n; i++) {c[i] = c[i - 1] + d[i];printf("%d\n", h + c[i]);}cout << endl;
}

凡人追妹传之大学篇

可以插入到中间,左边和右边,也有可能无法插入

分别进行判断即可

我就想着不算难吧,但是就只有几个人写了

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int cb[100000];
int cc[100000][2];int main() {int n;while (cin >> n) {for (int i = 0; i < n; i++) {cin >> cb[i];}sort(cb, cb + n);if (n == 1) {cout << "-1\n";} else if (n == 2) {//左边 右边 中间  int c = cb[1] - cb[0];if (c & 1) {cout << "2\n";cout << cb[0] - c << " " << cb[1] + c << "\n";} else if (cb[0] == cb[1]) {cout << "1\n";cout << cb[0] << "\n";} else {cout << "3\n";cout << cb[0] - c << " " << cb[0] + c / 2 << " " << cb[1] + c << "\n";}} else if (n >= 3) {//两个中间,左边右边,没有 //判断所有只有一个不等--中间int pd = 0;int min = INF;for (int i = 1; i < n; i++) {//找最小的 if (cb[i] - cb[i - 1] < min) {min = cb[i] - cb[i - 1];}}for (int i = 1; i < n; i++) {if ((cb[i] - cb[i - 1]) != min && (cb[i] - cb[i - 1]) == min * 2) {//可以插入 cc[pd][0] = cb[i];cc[pd++][1] = cb[i - 1];} else if ((cb[i] - cb[i - 1]) != min) {pd = -1;//直接失败 break;}}//全部相同int q = 1;for (int i = 1; i < n; i++) {if (cb[i] != cb[i - 1]) {q = 0;}}if (q) {cout << "1\n";cout << cb[0] << "\n";} else {if (pd > 1 || pd == -1) {//>=一个不等--没有 cout << "0\n";} else if (pd == 1) {cout << "1\n";cout << (cc[0][0] + cc[0][1]) / 2 << "\n";} else if (pd == 0) {//所有都等,左右 int c = cb[1] - cb[0];cout << "2\n";cout << cb[0] - c << " " << cb[n - 1] + c << "\n";}}}}
}

北宋大烟篓

经典约瑟夫环问题

如果看不懂代码的可以看这里

https://blog.csdn.net/u011500062/article/details/72855826

#include <iostream>
#include <algorithm>using namespace std;int cir(int n, int m) {int p = 0;for (int i = 2; i <= n; i++) {p = (p + m) % i;}return p + 1;
}int main() {int t;int n, m;cin >> t;for (int i = 0; i < t; i++) {cin >> n >> m;cout << cir(n, m) << "\n";}
}

游戏败家子

动态规划
假设数组 cost 的长度为 n,则 n个阶梯分别对应下标 0 到 n-1,楼层顶部对应下标 n,问题等价于计算达到下标 n 的最小花费。可以通过动态规划求解。

创建长度为 n+1 的数组dp,其中dp[i] 表示达到下标 i的最小花费。

由于可以选择下标 0或 1 作为初始阶梯,因此有 dp[0]=dp[1]=0。

当 2≤i≤n 时,可以从下标 i−1 使用 cost[i−1] 的花费达到下标 i,或者从下标 i-2使用 cost[i−2] 的花费达到下标 i。为了使总花费最小,dp[i] 应取上述两项的最小值,因此状态转移方程如下:

dp[i]=min(dp[i−1]+cost[i−1],dp[i−2]+cost[i−2])

依次计算 dp 中的每一项的值,最终得到的dp[n]即为达到楼层顶部的最小花费。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>int minCostClimbingStairs(int *cost, int costSize) {int dp[costSize];dp[0] = cost[0];dp[1] = cost[1];for (int i = 2; i < costSize; i++) {dp[i] = fmin(dp[i - 1], dp[i - 2]) + cost[i];}return fmin(dp[costSize - 1], dp[costSize - 2]);
}int main() {int cost[1000];int costSize = 0;int n;while (~scanf("%d", &n)) {while (n--) {scanf("%d", &costSize);for (int i = 0; i < costSize; i++) {scanf("%d", &cost[i]);}printf("%d", minCostClimbingStairs(cost, costSize));}}}

超神排位赛

模拟题,灵感来自某年山东省省赛,有一道炉石的排位机制模拟

按照题意模拟即可,只是细节要注意,例如升段的时候,降段位的时候,王者50星,王者不会掉到星耀等几种情况

#include<bits/stdc++.h>using namespace std;char r[10][20] = {"", "Bronze", "Silver", "Gold", "Platinum", "Diamond", "Starry", "Master", "Challenger"};
int limit[] = {0, 3, 3, 4, 5, 5, 5, 999, 999};//星数限制
int limit2[] = {0, 3, 4, 4, 5, 5, 5, 999, 999};//分段数量限制
int rule[] = {0, 3, 3, 3, 4, 5, 6, 999, 999};//连胜规则数量
char br[6][10] = {"", "one", "two", "three", "four", "five"};
//cnt 段位下标   counter 小段位下标
int cnt, counter;
char c1[20], c2[20];
int c, n;void ascertain() {//cnt 段位下标   counter 小段位下标 for (int i = 0; i < 9; i++) {if (strcmp(c1, r[i]) == 0) {//相同cnt = i;break;}}for (int i = 0; i < 6; i++) {if (strcmp(c2, br[i]) == 0) {counter = i;break;}}
}void verify() {//王者判定 if (c > limit[cnt] && cnt != 7) {c -= limit[cnt];counter--;if (counter == 0) {cnt++;counter = limit2[cnt];}}
}int main() {int cb[1000];while (cin >> c1 >> c2 >> c) {ascertain();//使cnt,counter,c转化为数字cin >> n;int plus = 0;for (int i = 0; i < n; i++) {cin >> cb[i];//判断连胜的过程//判断加星升段的过程 if (cb[i] == 1) {//连胜场数 plus++;} else {plus = 0;}if (plus == rule[cnt] && cb[i] == 1) {//可以连胜 c += 2;verify();plus = 0;} else if (cb[i] == 1) {//普通胜利 c++;verify();} else if (cb[i] == -1) {//本身段位是0的可能,退小段位,大段位 if (cnt == 1 && counter == 3 && c == 0 || cnt == 7 && c == 0) {continue;//青铜,王者的特殊情况 }c--;if (c == -1) {//掉小段位counter++;if (counter == limit2[cnt] + 1) {//掉大段位counter = 1;cnt--;}c = limit[cnt] - 1;}}}if (cnt == 7 && c < 50) {//王者 cout << r[cnt] << " " << c << "\n";} else if (cnt == 7 && c >= 50) {//荣耀王者 cout << r[8] << "\n";} else {cout << r[cnt] << " " << br[counter] << " " << c << "\n";}}
}

这个大师太过正经

简单快速幂

按照一般的暴力过不了

#include<stdio.h>typedef long long ll;int main() {ll t;scanf("%lld", &t);while (t--) {ll n, a, b, p = 1000003;ll res = 0;scanf("%lld", &n);for (ll i = 0; i < n; i++) {ll q = 1;scanf("%lld %lld", &a, &b);while (b) {if (b & 1)q = q * a % p;b >>= 1;a = a * a % p;}res = (res + q) % p;}printf("%lld\n", res % p);}return 0;
}

糖果的四十六亿种分法

题意:有n个盒子组成一个圆,盒子里总共有不超过n个蛋糕,有的有好几个,有的为0。可以将一个盒子里的蛋糕往左右两个盒子里移动,一次只能移动一个,使最终每个盒子里有不超过一个蛋糕(可以没有),求最小的移动数

思路:把盒子分为两种,有蛋糕和没蛋糕的,然后建图,对于有蛋糕的盒子拆点,拆为蛋糕数-1个点,因为它本身留一个蛋糕不移动。需要注意的是因为是个圆,所以移动的路径肯定不会大于n/2,大于n/2时判断一下就好了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>using namespace std;const int N = 510;
const int INF = 0x3f3f3f3f;
int n, nx, ny;
int lx[N], ly[N], slack[N], match[N], s[N][N];
bool visx[N], visy[N];
int v[N], tmp[N];bool hungary(int v) {visx[v] = true;for (int i = 0; i < ny; i++) {if (visy[i]) continue;if (lx[v] + ly[i] == s[v][i]) {visy[i] = true;if (match[i] == -1 || hungary(match[i])) {match[i] = v;return true;}} else slack[i] = min(slack[i], lx[v] + ly[i] - s[v][i]);}return false;
}void km() {memset(match, -1, sizeof match);memset(ly, 0, sizeof ly);for (int i = 0; i < nx; i++)lx[i] = -INF;for (int i = 0; i < nx; i++)for (int j = 0; j < ny; j++)lx[i] = max(lx[i], s[i][j]);for (int i = 0; i < nx; i++) {memset(slack, 0x3f, sizeof slack);while (true) {memset(visx, 0, sizeof visx);memset(visy, 0, sizeof visy);if (hungary(i)) break;else {int d = INF;for (int j = 0; j < ny; j++)if (!visy[j]) d = min(d, slack[j]);for (int j = 0; j < nx; j++)if (visx[j]) lx[j] -= d;for (int j = 0; j < ny; j++)if (visy[j]) ly[j] += d;else slack[j] -= d;}}}
}int main() {int n;int a;cin >> a;while (a--) {cin >> n;int t = n / 2;for (int i = 0; i < n; i++)scanf("%d", v + i);for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)s[i][j] = -INF;int cnt1 = 0, cnt2 = 0;for (int i = 0; i < n; i++)if (v[i] == 0)tmp[i] = cnt2++;for (int i = 0; i < n; i++)for (int j = 0; j < v[i] - 1; j++) {for (int k = 0; k < n; k++) {if (v[k] == 0) {if (abs(k - i) >= t)s[cnt1][tmp[k]] = -(n - abs(k - i));elses[cnt1][tmp[k]] = -abs(k - i);}}cnt1++;}nx = cnt1, ny = cnt2;km();int res = 0;for (int i = 0; i < ny; i++)if (match[i] != -1)res += s[match[i]][i];printf("%d\n", -res);}return 0;
}

我有一座研究院

过题人数最多的一道题

三种方法:暴力,贪心,公式

暴力

如果哪边的轻就加哪边,直到一边数量已经到达一半

#include<iostream>
#include<cmath>using namespace std;int main() {int t;cin >> t;while (t--) {int a = 0, b = 0, n, ta = 0, tb = 0;cin >> n;for (int i = n; i > 0; i--) {if (ta == n / 2) {b += pow(2, i);tb++;} else if (tb == n / 2) {a += pow(2, i);ta++;} else if (a <= b) {a += pow(2, i);ta++;} else if (a > b) {b += pow(2, i);tb++;}}cout << abs(a - b) << "\n";}return 0;
}

贪心

最后一个和前n-1个是一组,其他是一组,因为要保持两边的绝对值最小

#include<cmath>
#include<iostream>using namespace std;int main() {int t;cin >> t;while (t--) {int a = 0, b = 0, n;cin >> n;a += pow(2, n);for (int i = 1; i < n / 2; i++) {a += pow(2, i);}for (int i = n / 2; i < n; i++) {b += pow(2, i);}cout << abs(a - b) << "\n";}return 0;
}

公式

我们可以得出规律,按照规律推导结果

#include<iostream>
#include<cmath>using namespace std;int main() {int t, n;cin >> t;while (t--) {cin >> n;cout << pow(2, n / 2 + 1) - 2 << "\n";}return 0;
}

特拉福珠宝俱乐部

题意:
求树上每个点能走出的最远距离

思路:
树形DP
程序中的数据结构:
A数组记录V结点沿子树方向最长路所经过V的孩子编号。
B数组记录沿子树方向的次长路长度。
dp1数组 记录子树方向的最长路。
dp2数组记录来自父节点的最长路。
vectorcnt:记录每条边的信息。
我们假设一个结点V的孩子为{v1,v2,v3……vn};

  1. 如果vi在V沿子树方向的最长路上
    那么dis【vi】 = max(dp1【vi】,max(dp2【V】,B【V】) + dis(V,vi))
    说一下内嵌的max,以图中2(V)结点2结点来自父节点的最长路和2结点的子树方向次长路的较大值加上V 和vi的距离

  2. 如果vi不在V沿子树方向的最长路上
    那么dis【vi】= max(dp1【V】,dp2【V】) + dis(V, vi);
    最长路要么来自父节点子树方向的最长路加上dis(V,vi),要不来自父节点V的从V的父节点来的最长路 + dis(V, vi);

对于根节点特殊处理因为没有父节点只有次最长路,并且单孩子的结点没有次长路。

#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int INF = 510;
int n, A[INF], B[INF], dp1[INF],dp2[INF];
typedef pair<int, int> PLL;
vector<PLL>cnt[INF];int dfs1(int root){int len = cnt[root].size();if(!len){//搜索到叶子return 0;}int Max = -1, loc1 = -1, loc2 = -1;for(int i = 0; i < len; i++){//寻找最长路if(dfs1(cnt[root][i].first) + cnt[root][i].second > Max){Max = dfs1(cnt[root][i].first) + cnt[root][i].second;loc1 = i;}}dp1[root] = Max;Max = -1;A[root] = loc1;for(int i = 0; i < len; i++){//寻找次长路if(dp1[cnt[root][i].first] + cnt[root][i].second > Max && i != loc1){Max = dp1[cnt[root][i].first] +cnt[root][i].second;loc2 = i;}if(loc2 != -1)B[root] = Max;}return dp1[root];
}void dfs2(int root){int len = cnt[root].size();for(int i = 0; i < len; i++){if(i == A[root]){//这个孩子在沿子树方向的最长路径上dp2[cnt[root][i].first] = max(dp2[root], B[root]) + cnt[root][i].second;}else{dp2[cnt[root][i].first] = max(dp2[root], dp1[root]) + cnt[root][i].second;}dfs2(cnt[root][i].first);}
}
int main(){while(scanf("%d",&n) != EOF){memset(dp1, 0, sizeof(dp1));memset(B, 0, sizeof(B));memset(A, 0, sizeof(A));memset(dp2, 0, sizeof(dp2));for(int i = 1; i <= INF; i++){cnt[i].clear();}for(int i = 2; i <= n; i++){int x1, x2;scanf("%d%d", &x1, &x2);cnt[x1].push_back(make_pair(i, x2));}dfs1(1);dfs2(1);for(int i = 1; i <= n; i++){cout<<max(dp1[i], dp2[i])<<endl;}}return 0;
}

吃糖直播间

首先考虑最简单的情况。如果只有一个箱子,则选择该箱子,可以选择到最高总糖果数。如果只有两个箱子,则由于两个箱子相邻,不能同时选择,只能选择其中的一个箱子,因此选择其中糖果数较高的箱子进行选择,可以选择到最高总糖果数。

如果箱子数量大于两个,应该如何计算能够选择到的最高总糖果数呢?对于第 k(k>2) 个箱子,有两个选项:
1.选择第 k 个箱子,那么就不能选择第 k-1 个箱子,选择总糖果数为前 k-2 个箱子的最高总糖果数与第 k 个箱子的糖果数之和。
2.不选择第 k 个箱子,选择总糖果数为前 k-1 个箱子的最高总糖果数。

在两个选项中选择选择总糖果数较大的选项,该选项对应的选择总糖果数即为前 k 个箱子能选择到的最高总糖果数。

用 dp[i] 表示前 i 个箱子能选择到的最高总糖果数,那么就有如下的状态转移方程:
dp[i]=max(dp[i−2]+nums[i],dp[i−1])

边界条件为:
{
dp[0]=nums[0] 只有一个箱子,则吃该箱子中的糖果
dp[1]=max(nums[0],nums[1]) 有两个箱子,选择其中糖果数多的箱子。
}
最终的答案即为dp[n−1],其中 n 是数组的长度。

#include<stdio.h>
#include<iostream>using namespace std;
const int maxn = 110;int arr[maxn], dp[maxn][5];int main() {int t, cas = 0;cin >> t;while (t--) {int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> arr[i];}dp[1][0] = 0;dp[1][1] = arr[1];for (int i = 2; i <= n; i++) {dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);dp[i][1] = dp[i - 1][0] + arr[i];}printf("Case #%d:\n", ++cas);cout << max(dp[n][0], dp[n][1]) << endl;}
}

我师傅实在太稳健了

我觉得这个看了代码秒懂,这个也是签到题吧…

#include<iostream>using namespace std;int main() {int t;cin >> t;while (t--) {int a, b, c, d, e;cin >> a >> b >> c >> d >> e;if (a - b - c - d - e > 1 ||b - a - c - d - e > 1 ||c - d - e - a - b > 1 ||d - e - a - b - c > 1 ||e - a - b - c - d > 1) {cout << "no\n";} else {cout << "yes\n";}}return 0;
}

你看,是不是秒懂…

大奉卖笔人

大致思路如下:
1、先对输入的数组进行快速排序,从小到大排列
2、先进行第一步优化,将可以去掉的球先去掉,使后面的连续几类球都保持一样的数量,
在此过程中去掉的球的总价格计算进total里面,
这一步优化目的在于找到一个阈值threshold,使得去掉的球的数量threshold <= orders
一旦threshold > orders,结束此步。
这一步结束后,color_count表示优化了多少个类的球的数量,base表示下一步优化时球的基准,
optimize表示没有超过orders的最大threshold,即这一步去掉的球的总数。

例如:[2 4 6 8 10] orders = 20
-> [2 4 6 8 8] threshold = 10-(8×1) = 2 < orders
-> [2 4 6 6 6] threshold = (10+8)-(6×2) = 6 < orders
-> [2 4 4 4 4] threshold = (10+8+6)-(4×3) = 12 < orders
-> [2 2 2 2 2] threshold = (10+8+6+4)-(2×4) = 20 = orders
所以从[2 4 6 8 10]优化后是[2 2 2 2 2]
color_count = 4, base = 2,threshold = 20,optimize = 20

[2 4 6 8 10] orders = 23
-> [2 2 2 2 2] threshold = (10+8+6+4)-(2×4) = 20 < orders
-> [0 0 0 0 0] threshold = 10+8+6+4+2 = 30 > orders
所以从[2 4 6 8 10]优化后是[2 2 2 2 2]
color_count = 4, base = 2,threshold = 30,optimize = 20

3、这一步结束之后,我们已经去掉的球的数量是optimize,剩下的球的数量是orders-optimize
如果orders = optimize,直接返回total,就是最终的价格
否则再进行进一步优化
在第2步中的优化是从球最多的开始,每次优化1个,2个…n个球的数量
而在这一步中,现在要一次优化color_count个球的数量
在优化的过程,去掉的球的总价格就是color_count个等差数列的和
先计算(orders-optimize)/(color_count+1),得到等差数列的n
然后计算(order-optimize)%(color_count+1),得到计算完等差数列后剩下几个单独的球需要取出
a1 = base - n + 1
an = base
然后根据a1,an,n计算出等差数列的和,color_count个等差数列的和就是这一次优化的球的总价格
最后还剩下几个球要单独取出,它们的价格是base-n,数量 < color_count + 1
将批量的和单独的球的总价格都加进total里
最后得到total就是结果

注意在计算过程中注意数字溢出的问题

#include<iostream>using namespace std;void quickSort(int arr[], int low, int high, int size);int maxProfit(int *inventory, int inventorySize, int orders);int main() {int num;cin >> num;int size;int inventory[100000];int orders;while (num--) {cin >> size;for (int i = 0; i < size; i++) {cin >> inventory[i];}cin >> orders;cout << maxProfit(inventory, size, orders) << "\n";}
}void quickSort(int arr[], int low, int high, int size) {if (size == 1)return;if (size == 2) {if (arr[0] >= arr[1]) {int temp = arr[0];arr[0] = arr[1];arr[1] = temp;return;} elsereturn;}if (low >= high)return;int first = low;int last = high;int key = arr[first];while (first < last) {while (first < last && arr[last] >= key) {last--;}arr[first] = arr[last];while (first < last && arr[first] < key) {first++;}arr[last] = arr[first];}arr[first] = key;quickSort(arr, low, first - 1, size);quickSort(arr, first + 1, high, size);
}int maxProfit(int *inventory, int inventorySize, int orders) {quickSort(inventory, 0, inventorySize - 1, inventorySize);long int total = 0;if (inventorySize == 1) {long int a1 = inventory[0] - orders + 1;total = ((long int) orders * (a1 + (long int) inventory[0]) / 2) % 1000000007;return total;}int color_count = 0;long int balls_count = 0;long int threshold = 0;int optimize = 0;for (int m = inventorySize - 1; m >= 0; m--) {balls_count += (long int) inventory[m];if (m > 0)threshold = balls_count - (long int) (inventorySize - m) * inventory[m - 1];elsethreshold = balls_count;if (threshold <= (long int) orders) {optimize = threshold;color_count += 1;} elsebreak;}int base = 0;if (color_count == inventorySize)base = 0;elsebase = inventory[inventorySize - color_count - 1];for (int n = 0; n < color_count; n++) {total = (total +(long int) (inventory[inventorySize - n - 1] - base) * (base + 1 + inventory[inventorySize - n - 1]) /2) % 1000000007;}if (optimize == orders)return total;int left = orders - optimize;int times = left / (color_count + 1);int single = left % (color_count + 1);long int times_total = 0;int a1 = base - times + 1;times_total =((long int) times * ((long int) a1 + (long int) base) / 2 * (long int) (color_count + 1)) % 1000000007;;total = (total + times_total) % 1000000007;total = (total + (long int) (a1 - 1) * (long int) single) % 1000000007;return total;
}

最后预祝各位大佬在现场赛都能取得好成绩

2021-BNUZ-IT节程序设计竞赛网络赛题解相关推荐

  1. 2022-BNUZ-IT节程序设计竞赛网络赛题解

    IT节程序设计竞赛-网络赛题目解析 A-纯阳之体 解析 ​ 本题是一个双指针问题,当然直接暴力也是可以做的.主要思想就是先求最长连续且不含重复字符的字串的长度.有了长度之后就可以再进行一次搜索,当长度 ...

  2. 2019 ICPC中国邀请赛(南昌)暨国际丝绸之路程序设计竞赛-网络赛题解

    以下所有AC题解程序来自"仙客传奇"团队. AC题数:10/13 ABCDHIJKLM A. PERFECT NUMBER PROBLEM 解题思路:先编写离线程序计算出最小的5个 ...

  3. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解

    "科林明伦杯"哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解 萌新又来写题解啦 原题链接 B 减成一 题意:存在n个数,每次操作可以任选一个区间使得区间内的所有数字减一.问最少多 ...

  4. 2018中国大学生程序设计竞赛-网络选拔赛题解

    以下所有AC题解程序来自"仙客传奇"团队. A. Buy and Resell AC的C++语言程序: #include<iostream> #include<c ...

  5. 2012年北京师范大学新生程序设计竞赛网络赛

    好吧... bnu的OJ做的相当不错... 然后复习unix无聊了就拿这场做了水题... 两题不会做悲剧...... A. 校队的聚餐 Time Limit: 2000ms Case Time Lim ...

  6. 北京林业大学“计蒜客”杯程序设计竞赛 网络赛 马踏棋盘的问题

    //使用bfs #include<stdio.h> #include<iostream> #include<utility> #include<queue&g ...

  7. 北航第十二届程序设计竞赛网络预赛题解

    本次比赛共有 401 个用户通过至少一道题目,平均通过 3 题,第一位做出全部题目的同学用时 45:26:37 . 如果有对题目的疑问或是见解,欢迎寄刀片给出题人. 预祝大家在决赛中取得好成绩!没有搜 ...

  8. 湖南中医药大学信息科学与工程学院第四届大学生程序设计竞赛——正式赛题解

    目录 问题A:X星人的统计 问题B:X星人的报数 问题C:X星人的迷宫 问题D:X星人的高考 问题E:X星人的匹配 问题F:X星人的成绩 问题G:X星人的变换 问题H:X星人的游戏 问题I:X星人的宝 ...

  9. 2017年浙江理工大学程序设计竞赛校赛 题解源码(A.水, D. 简单贪心 ,E.数论,I 暴力)...

    Problem A: 回文 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 1719  Solved: 528 Description 小王想知道一个字 ...

最新文章

  1. linux cpp vscode远程调试 的配置
  2. iOS 在UILabel显示不同的字体和颜色(转)
  3. 知识管理促进企业组织能力提升
  4. 后台服务出现明显“变慢”,谈谈你的诊断思路?
  5. Java GUI界面
  6. 浅谈对px em rem的理解
  7. SQL关联查询————LEFT JOIN关键字的使用
  8. JDK、JRE、javac和JVM的关系
  9. 信息发布系统 Jquery+MVC架构开发(3) 解决方案创建
  10. 大数据Hadoop学习(一)入门
  11. 互联网公司的敏捷开发是怎么回事?这一份软件工程书单送给你!
  12. WPF 框架开发 加入 InternalsVisibleToAttribute 特性让其他程序集可以访问 internal 权限成员
  13. IAST 实践利用洞态做开源组件的安全治理
  14. SPFA算法模板(刘汝佳版)--Wormholes POJ - 3259
  15. Windbg的获取与安装教程
  16. Pytorch训练问题:AssertionError: Invalid device id
  17. 【Linux 内核 内存管理】内存映射相关数据结构 ③ ( vm_area_struct 结构体成员分析 | shared 成员 | anon_vma_chain 成员 | anon_vma 成员 )
  18. 微信小程序章节自测--6-7-8-9-有解析
  19. 服务器和PC Server介绍
  20. 用python或者vba把一个excel表格拆分成多个excel表格

热门文章

  1. 吴恩达深度学习课程翻译
  2. 深入浅出matplotlib(65): 绘制条形堆积图
  3. 乒乓球比赛人员对战比赛名单
  4. 变压器的二次侧电压分析
  5. 阿里巴巴历年在线笔试题汇总
  6. “工二代”烧了毕业证后
  7. python标识符命名规则
  8. Nvidia Drive Orin/Drive AGX Orin DRIVE OS相关资源介绍
  9. python_图片透明化
  10. 诚之和:今年市值蒸发2323亿港元,海底捞关店的真正原因是什么?