文章目录

  • 中国石油大学ACM俱乐部开放训练赛
    • A. sciorz画画(凸多边形最优三角型剖分,区间DP)
    • B. 奎奎发红包(贪心)
    • C. 关于我转生变成史莱姆这档事(DFS)
    • F. 求和(矩阵构造+矩阵快速幂)
    • K. 数学问题(组合数预处理+二维前缀和)

中国石油大学ACM俱乐部开放训练赛

A. sciorz画画(凸多边形最优三角型剖分,区间DP)

  • 题目

    多边形的每个顶点都有一个权值a[i],要用n-3条不相交的线将这个n边形分割成n-2个三角形,每个三角形的价值等于三个顶点权值的乘积。
    问怎么分隔才能使得n-2个三角形的价值和最大

  • 输入

    2     1<=t<=100
    3       1<=n<=100
    1 2 3   1<=a[i]<=100
    4
    1 2 3 4
    
  • 输出

    Case #1: 6
    Case #2: 32
    

dp[i][j]表示从第i个到第j个点的最优剖分答案

  1. j=ij=i+1时,无法构成三角形,dp[i][j]=0
  2. j>=i+2时,在ij之间取一个分割点k。此时多边形被划分为3部分:ik部分,kj部分,三角形i,j,k。其中ik部分和kj部分都是子问题,可以利用之前求出的结果

dp[i][j]=max⁡k=i+1j−1{dp[i][j],dp[i][k]+dp[k][j]+cost(i,j,k)}dp[i][j]=\max_{k=i+1}^{j-1}\lbrace dp[i][j],dp[i][k]+dp[k][j]+cost(i,j,k)\rbrace dp[i][j]=k=i+1maxj−1​{dp[i][j],dp[i][k]+dp[k][j]+cost(i,j,k)}

注意:因为区间DP需要用到子区间的结果,所以区间需要由小到大,因而区间起点i是从n-1到1

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 100 + 10;
int n, a[maxn];
int dp[maxn][maxn];
void solve()
{mem(dp, 0);for (int i = n-1; i >=1; i--) {    //由小到大for (int j = i + 2; j <= n; j++) {for (int k = i + 1; k <= j - 1; k++) {dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[j] * a[k]);}}}cout << dp[1][n] << endl;
}
int main()
{ios::sync_with_stdio(0), cin.tie(0);int t;cin >> t;for (int i = 1; i <= t; i++) {cin >> n; cout << "Case #" << i << ": ";for (int j = 1; j <= n; j++) {cin >> a[j];}solve();}
}

B. 奎奎发红包(贪心)

  • 题目

    奎奎给n个人发红包,每个人都两个值v[i]t[i]t[i]代表给第i个人发红包所需的时间。
    每个人的红包大小为v[i]*tt表示这个人的等待时间(包括自己所需时间)。
    问最少花多少钱能满足每一个人?

  • 输入

    4
    1 4
    2 3
    3 2
    4 1
    
  • 输出

    35
    

考虑相邻的两个人a,b,如果a排在前面,代价为a.v∗a.t+b.v∗(a.t+b.t)a.v*a.t+b.v*(a.t+b.t)a.v∗a.t+b.v∗(a.t+b.t);如果b排在前面,代价为b.v∗b.t+a.v∗(a.t+b.t)b.v*b.t+a.v*(a.t+b.t)b.v∗b.t+a.v∗(a.t+b.t)。对两式进行化简得:如果a.t∗b.v<a.v∗b.ta.t*b.v<a.v*b.ta.t∗b.v<a.v∗b.t,则a应该排在前面,也就是a.ta.v<b.tb.v\frac{a.t}{a.v}<\frac{b.t}{b.v}a.va.t​<b.vb.t​
所以按照tv\frac{t}{v}vt​的排序,但需要特别考虑0的情况,因为v=0时不用花钱,所以可以放到最后不管。

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 1e5 + 10;
struct node {int v, t;bool operator<(const node b) const{return 1.0 * this->t / this->v < 1.0 * b.t / b.v;}
} a[maxn];
int n, t, v, num;
bool cmp(node a, node b)
{return 1.0 * a.t / a.v < 1.0 * b.t / b.v;
}
int main()
{ios::sync_with_stdio(0), cin.tie(0);cin >> n;for (int i = 1; i <= n; i++) {cin >> v >> t;if (v != 0) {a[i].v = v;a[i].t = t;num++;}}sort(a + 1, a + 1 + num);ll ans = 0, sum = 0;for (int i = 1; i <= num; i++) {sum += a[i].t;ans += a[i].v * sum;}cout << ans << endl;
}

C. 关于我转生变成史莱姆这档事(DFS)

  • 题目:

    史莱姆要吃掉总量为S的魔素,并且每一天吃掉的魔素都要为前一天的2~9倍(整数倍)
    求最短的天数并且要恰好吃完所有的魔素

  • 输入:

    571
    
  • 输出:

    5
    

将题目进行用表达式表达:

因此可以进行暴搜,将括号一层一层拆开,只要每一层都能满足整除关系即可。
如:先对sss进行因数分解,得到a1a_1a1​的值,然后将括号打开,令s′=sa1−1s'=\frac{s}{a_1}-1s′=a1​s​−1。
之后的递归只需要考虑2~9是否是s′s's′的因子,如果是的话就可以再次拆开括号,继续递归s′′s''s′′

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
typedef long long ll;
const int INF = 1 << 30;
int s, ans;
int dfs(int s)
{if (s >= 2 && s <= 9) return 1;int ans = INF;for (int i = 2; i <= 9; i++) {if (s % i == 0) {ans = min(ans, dfs(s / i - 1) + 1);}}return ans;
}
int main()
{ios::sync_with_stdio(0), cin.tie(0);cin >> s;ans = INF;for (int i = 1; i * i <= s; i++) {if (s % i == 0) {ans = min(ans, dfs(s / i - 1) + 1);if (i != s / i) {ans = min(ans, dfs(i - 1) + 1);}}}cout << (ans == INF ? -1 : ans) << endl;
}

F. 求和(矩阵构造+矩阵快速幂)

  • 题目

    已知An*n矩阵,求S=A+A2+A3+⋯+AmS=A+A^2+A^3+\dots+A^mS=A+A2+A3+⋯+Am中每一项对1e9+7取模后的值

  • 输入

    1 2019
    1
    
  • 输出

    2019
    

可以构造一个矩阵B=[AA0E]B=\begin{bmatrix}A & A\\0 & E\\ \end{bmatrix}B=[A0​AE​]

可以发现:B2=[A2A+A20E]B^2=\begin{bmatrix}A^2 & A+A^2\\0 & E\\ \end{bmatrix}B2=[A20​A+A2E​]

B3=[A3A+A2+A30E]B^3=\begin{bmatrix}A^3 & A+A^2+A^3\\0 & E\\ \end{bmatrix}B3=[A30​A+A2+A3E​]

Bm=[AmA+A2+A3+⋯+Am0E]B^m=\begin{bmatrix}A^m & A+A^2+A^3+\dots+A^m\\0 & E\\ \end{bmatrix}Bm=[Am0​A+A2+A3+⋯+AmE​]

所以只需求出BmB^mBm即可

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
typedef long long ll;
const int MOD = 1000000007;
const int maxn = 60 + 10;
int n, m;
struct Matrix {ll m[maxn][maxn];Matrix() { memset(m, 0, sizeof(m)); }
} a, b, ans;
Matrix Multi(Matrix a, Matrix b) //矩阵乘法
{Matrix res;for (int i = 0; i < maxn; i++) {for (int j = 0; j < maxn; j++) {for (int k = 0; k < maxn; k++) {res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;}}}return res;
}
Matrix fastm(Matrix a, int n) //矩阵快速幂
{Matrix res;for (int i = 0; i < maxn; i++) { //初始化为单位矩阵res.m[i][i] = 1;}while (n) {if (n & 1) {res = Multi(res, a);}a = Multi(a, a);n >>= 1;}return res;
}
int main()
{ios::sync_with_stdio(0), cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {cin >> a.m[i][j];b.m[i][j] = a.m[i][j];}}//构造bfor (int i = 1; i <= n; i++) {for (int j = n + 1; j <= 2 * n; j++) {b.m[i][j] = a.m[i][j - n];}}for (int i = n + 1; i <= 2 * n; i++) {b.m[i][i]=1;}ans = fastm(b, m);for (int i = 1; i <= n; i++) {for (int j = n + 1; j <= 2 * n; j++) {cout << ans.m[i][j] % MOD << " ";}cout << endl;}
}

K. 数学问题(组合数预处理+二维前缀和)

  • 题目

    给出整数n,m,g,求有多少对(i,j)满足g整除CijC_i^{j}Cij​,其中0≤i≤n,0≤j≤min⁡(i,m)0\le i\le n,0\le j\le \min (i,m)0≤i≤n,0≤j≤min(i,m)

  • 输入

    1    //T组数据
    4   //g
    5 4 //n,m
    
  • 输出

    2
    

判断g是否整除CijC_i^{j}Cij​,就是判断Cij%gC_i^{j}\,\%\,gCij​%g是否为0。

对于组合数的计算,可以依据组合数的递推公式,Cij=Ci−1j−1+Cij−1C_i^j=C_{i-1}^{j-1}+C_i^{j-1}Cij​=Ci−1j−1​+Cij−1​
然后对CijC_i^jCij​进行取模,就转化为Cij==0C_i^j==0Cij​==0时满足条件

但组数有1e4,n,m数据范围为2e3,所以可以利用二位前缀和s[i][j]=s[i−1][j]+s[i][j−1]−s[i−1][j−1]s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]s[i][j]=s[i−1][j]+s[i][j−1]−s[i−1][j−1]将范围内所有整数对的结果进行预处理,每次的查询就优化到了O(1)

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 2e3 + 10;
int n, m, g;
ll c[maxn][maxn], s[maxn][maxn];
void solve()
{//预处理组合数c[1][1] = 1;for (int i = 0; i <= 2000; i++) c[i][0] = 1;for (int i = 2; i <= 2000; i++) {for (int j = 1; j <= i; j++) {c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % g;}}//二位前缀和统计所有整数对的答案for (int i = 2; i <= 2000; i++) {for (int j = 1; j <= i; j++) {s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];if (c[i][j] == 0) s[i][j] += 1;}//考虑m大于n的情况for (int j = i + 1; j <= 2000; j++) {s[i][j] = s[i][i];}}
}
int main()
{ios::sync_with_stdio(0), cin.tie(0);int t;cin >> t >> g;solve();for (int i = 1; i <= t; i++) {cin >> n >> m;cout << s[n][m] << endl;}return 0;
}

中国石油大学ACM俱乐部开放训练赛相关推荐

  1. 17暑期ACM俱乐部个人训练赛第1场 (石油oj) 7.24号

    //暑假训练第一场,孤军奋斗,事后各种补题,(ps,说实话,时间点卡的不是很好,12点到17点, 没有午觉,大脑犯困, 各种困,各种累,再者,自己也慢慢的发现 精力开始不放在算法上了, 很多时候在做其 ...

  2. 北方大学 ACM 多校训练赛 第十五场 欢度6.18

    把式子变成a[i]+1 = p(a[i-1]+1)+q[a[i-2]+1],矩阵快速幂搞定.复杂度o(logn) #include <iostream> #include <cstd ...

  3. 北方大学 ACM 多校训练赛 第十五场 买花

    显然是一个比较简单的离线查询问题. 本质上是对区间求集合的问题,按照区间右端点从小到大对区间进行排序,然后用一个指针curr表示当前正在考虑区间的最右侧位置,针对排好序区间[tarl,tarr],先查 ...

  4. 北方大学 ACM 多校训练赛 第十五场 数字游戏

    本题的意思是,给你1/2,1/2,1,2,4--2^(k-1) ,让你在左边的数列中添加+号或者-号,使得最终的答案为n即可. 思路: 我们知道上面这些数直接如果全部都填+号的话,那么最终得到的数为2 ...

  5. 北方大学 ACM 多校训练赛 第十五场 蜘蛛牌A

    题目描述 XCX最近迷上了玩蜘蛛牌.蜘蛛牌是windowsxp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比它大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌 ...

  6. 北方大学 ACM 多校训练赛 第四场 题解

    A. 恶魔包毁灭世界 已知一张二分图,问哪些边是二分图的可行边? 先跑最小流,再把残余网络建图,几个重要结论是: ·最小割的可行边(满流&&2点不在一个SCC中) ·最小割的必行边(可 ...

  7. 北方大学 ACM 多校训练赛 第五场(D. 节操大师 - 二分)

    Description MK和他的小伙伴们(共n人,且保证n为2的正整数幂)想要比试一下谁更有节操,于是他们组织了一场节操淘汰赛.他们的比赛规则简单而暴力:两人的节操正面相撞,碎的一方出局,而没碎的一 ...

  8. 2018年ACM俱乐部个人训练赛第二十一场.A.微信群

    问题 A: 微信群 时间限制: 1 Sec   内存限制: 128 MB 提交: 272   解决: 67 [ 提交][ 状态][ 讨论版][命题人: admin] 题目描述 众所周知,一个有着6个人 ...

  9. 2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html 题目传送门 - 2018牛客多校赛第二场 E ...

最新文章

  1. 为什么会出现docker
  2. 9、MySQL逻辑架构介绍
  3. Google Maps 补丁绕过、得双倍奖金这么简单?我陷入了自我怀疑
  4. 今年要如何准备?想去阿里/美团/头条做机器学习工程师
  5. 利用matlab写一个简单的拉普拉斯变换提取图像边缘
  6. 如何生成二维码及注意事项
  7. 2019测试指南-web应用程序安全测试(二)识别应用程序入口点
  8. 专利申请模板,包含实用新型专利和发明专利模板
  9. tftp拷贝linux文件夹,CentOS下使用TFTP向目标板传送文件
  10. 老毛子 K2 通过SSH 抓包
  11. 消息队列——ActiveMQ使用及原理浅析
  12. Android手机会中电脑病毒么,安卓手机中木马病毒怎么办
  13. 区块链开发入门书籍推荐
  14. 方正税控计算机配置,方正计算机U盘启动优先级的BIOS设置说明_IT /计算机_信息...
  15. 贴片钽电容的封装、尺寸和标…
  16. 关于网络、交换机、路由器
  17. 苹果8官方主板价格_苹果官方确认iPhone8主板问题_TOM科技
  18. 如何将计算机网络设置为家庭网络连接打印机共享,怎样设置家庭网络打印机共享...
  19. mosquitto 群晖下载_告诉你如何轻松解决NAS系统搬家任务,群晖系统的乾坤大挪移...
  20. ADOBE全系破解文件(无解压密

热门文章

  1. NLP的介绍和如何利用机器学习进行NLP以及三种NLP技术的详细介绍
  2. [随文杂记]收藏一个爆笑笑话。
  3. 不要刻意改变,做自己就好
  4. 在Ubuntu主机上使用USB无线网卡
  5. Uniapp 引入css
  6. VS 项目属性打不开
  7. 上海合合信息科技有限公司--深度学习算法实习生--面试题整理
  8. 工业互联网平台-厂商及产品调研
  9. 第四届蓝桥杯C++B组国(决)赛真题
  10. shell特殊符号解释