这么水的校内赛居然能卡掉五道,真是人间奇葩,能给自己气死。
D-矩阵
题面
体育老师觉得继续刁难小R不太好,所以他对小R发起了“扣平时分”威胁!
这一次他和之前不一样了,让所有同学站成一个矩形,然后他会随机点一个人,被点中的人的那一行和那一列上的所有人都会加上一个值,经过若干次点名之后,老师想让小R告诉他,数值最大的和最小的相差多少?
输入
第一行输入三个整数n(表示矩阵的行数),m(表示矩阵的列数)和q(表示老师点名的次数)。
之后q行,每行三个整数(x,y,val),x和y表示被点名同学的坐标,val表示加上的值。
输出
输出一行,表示最大和最小相差的值。
样例
样例输入 3 3 3 1 1 1 2 2 2 3 3 3
样例输出 4
数据范围
1 <= x <= n <= 2000
1 <= y <= m <= 2000
-1000000 <= val <= 1000000
0 <= q <= 10000
基础模拟题,没什么好说的。需要注意的点是对于每一个被查询的点(x,y)需要预先减去一个v值,不然会重复计算,赛时就死在这,fo了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define get(x) scanf("%d", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)
using namespace std;
const int INF = 0X7F7F7F7F;
const int LIM = 2005;
long long a[LIM][LIM];
int n, m, q;
int x, y;
long long v;
void plu(int x, int y, int v)
{
rep(i, 1, n) a[i][y] += v;
rep(i, 1, m) a[x][i] += v;
}
long long find()
{
long long ma = 0;
long long mi = 1e9;
rep(i, 1, n) rep(j, 1, m)
{
ma = max(ma, a[i][j]);
mi = min(mi, a[i][j]);
}
return ma - mi;
}
int main()
{
get(n); get(m); get(q);
while (q--)
{
get(x); get(y); get(v);
a[x][y] -= v; //去重
plu(x, y, v);
printf("%lld", find());
}
return 0;
}
E-分组
题面
期末要到了,体育老师终于要做一回好人了,他想让大家放松一下,决定权落到了小R手里。
老师想到了一个游戏,让所有人都参与,但是怎么分组问题就来了,他既想每个组男女生一样多,也想分的组最多。
如果小R分错了,那这次体育课怕是要换成数学课了。
每个组分多少人合适?男女比例如何?又分了多少个组?
输入
输入一行,两个整数n,m 分别表示全班男生人数和女生人数。
(0<=n,m<= 10000000)
输出
如果存在分组的方式,输出一行,四个整数a,b,c,d。分别表示每组的人数,男女生比例(最简比例形式),分的组数。
如果不存在,输出”There is no grouping method!”(输出数据不含引号)。
样例数据
样例输入 48 56
样例输出 13 6 7 8
就很简单的gcd,取mgcd=gcd(n,m),这个mgcd就是分的组数。至于赛时很多铁汁纠结的男或女为0的情况,则可以用与运算来判断是否存在0。
这题漏掉的原因是我觉得太简单先去A后面的,没想到被杨辉三角卡了一年,服气。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define get(x) scanf("%d", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)
using namespace std;
const int INF = 0X7F7F7F7F;
int gcd(int a, int b)
{
return !b ? a : gcd(b, a%b);
}
int n, m;
int mgcd;
int main()
{
get(n); get(m);
mgcd = gcd(n, m);
if(m & n) printf("%d %d %d %d", (n+m)/mgcd, n/mgcd, m/mgcd, mgcd);
else cout << "There is no grouping method!";
return 0;
}
F-体育课or数学课?
题面
小R想提高自己数学能力,体育课上,故意分错了组队,成为了大家的公敌。
数学课上,老师想让大家了解杨辉三角的构造原理,如果有人能回答出杨辉三角的第n行m列的数字是什么,那这次课还是可以继续回去上体育课的。
这个问题也太难了吧,为了让大家原谅自己,小R毅然挺身而出,回答了老师的每一次询问。小R的答案是多少?
输入
输入一行,一个整数n,表示老师的询问次数。
接下来n行,每行两个整数x,y。表示老师询问的坐标。
1 <= n <= 10000000,1 <= x, y <= 2000
输出
输出n行,每行一个整数,表示小R的回答。
由于输出的数可能很大,只需输出结果对 15905368710取模就行
如果老师询问不存在输出”No problem”(输出数据不含引号)。
样例数据
样例输入 5 1 1 3 2 3 4 4 2 6 3
样例输出 1 2 No problem 3 10
能被杨辉三角卡将近一个小时也是滑天下之大稽,最开始写组合数写了半天,然后发现这题要模大数,又换暴力,暴力死活re,疯狂debug又继续疯狂re,最后就炸了。
其实到现在也不知道为什么会re,重写了一遍代码,清爽多了也就过了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define get(x) scanf("%d", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)
using namespace std;
const int INF = 0X7F7F7F7F;
const int LIM = 3005;
const long long MOD = 15905368710;
int t, n, x, y;
long long a[LIM][LIM];
int main()
{
get(t);
a[1][1] = 1;
rep(i, 2, 2000) rep(j, 1, i)
a[i][j] = (a[i-1][j-1] % MOD + a[i-1][j] % MOD) % MOD;
rep(i, 1, t)
{
get(x);get(y);
if(y > x) printf("No problem\n");
else printf("%lld\n", a[x][y]);
}
return 0;
}
H-几何
题面
小R沉迷于数学作业无法自拔,导致他又忘记了今天有体育课的事情,好吧,现在还不迟,还剩最后一道题目他就写完作业啦,跑过去上体育课还不算太迟最多被罚着跑跑圈的样子,说到跑圈,因为体育老师已经不满足让他按照操场跑圈了,而是规定了操场上的三棵树,要求他每一次都需要绕着一棵树跑完一圈之后跑到下一棵树,而且必须要求绕树跑的时候跑步轨迹为以三棵树为圆心的圆,哇体育老师也太变态了,体育老师想知道什么时候可以使得小R的跑步路径最长呢?聪明的你一定知道是三个圆相互外切的时候,但操场上有那么多的树要怎么选呀,聪明的你帮体育老师选一下满足条件的树吧,但是你只知道一些树之间的距离,但是这也难不到你的!
输入
输入一行为三个正整数,表示树之间的距离,均不超过1e9
输出
如果三个距离不能构成三角形,则输出“No triangles”
如果三条边能构成三角形但不能画出符合要求的圆形的路径,输出“No”
否则输出一行“Yes”然后在第二行输出一组方案,按升序给出三个圆形路径的半径,保留两位小数
样例数据
样例输入 2 3 3
样例输出 Yes 1.00 1.00 2.00
很简单的三元一次,而且系数一定为1。赛时想复杂了,套了个用矩阵消元做的三元一次方程通解板子,死活没整出来,后面就没时间了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define get(x) scanf("%lf", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)
using namespace std;
const int INF = 0X7F7F7F7F;
double x, y, z;
double ans[5];
int main()
{
get(x); get(y); get(z);
if (x+y <= z || x+z <= y || y+z <= x)
{
cout << "No triangles";
return 0;
}
ans[1] = (x+y-z) / 2;
ans[2] = (x+z-y) / 2;
ans[3] = (z+y-x) / 2;
sort(ans+1, ans+4);
cout << "Yes" << endl;
printf("%.2lf %.2lf %.2lf", ans[1], ans[2], ans[3]);
return 0;
}
J-抽扑克
题面:
其实众所周知的是,集训队有两个小R……他们的分别是RT和RJ,也是这一场的出题人,终于出完题了,也不用被体育老师罚跑圈了,虽然题目背景纯属虚构,但是两个小R都非常非常非常不喜欢体育课,其实也算是题目来源于生活?
现在趁大家在考试,他们开始玩游戏,疫情期间条件简陋来抽扑克吧,游戏规则如下:
初始一共有n张卡牌
先手第一步最少要拿1张牌,最多要拿n-1张牌。
接下来每一步,双方最少要拿1张牌,最多拿等同于上一步对方拿的牌数的牌。
拿走最后一张牌的人将获得游戏胜利。
每一次都是RJ先拿。
此时,群主作为集训队最顶端的存在,他总是能一下子猜对两个人的胜负情况,这让小R们非常不爽,但是又不得不服气,游戏突然之间就变得索然无味。好难过。不如你也来猜一猜两个人谁会赢吧。
输入
输入数据包含一个整数n,表示初始的扑克数量,2<=n<=1e18
输出
如果这一次比赛是RJ赢了,则输出“RJ is winner.”(输出数据不含引号)
如果是RT赢了,则输出“RT is winner.”(输出数据不含引号)
样例数据
样例输入 2
样例输出 RT is winner
这题与牛客59的D题有异曲同工的地方。其实不难思考出来,赛时应该是时间不够加上疯狂re导致心态爆炸,没有仔细分析它,实在可惜。
对于题目数据做以下思考:
- n=2,RJ只能拿一张,剩一张RT拿下然后赢;
- n=3,RJ可以只拿一张,然后情况回到n=2时,RJ 赢;
- n=4,RJ不论拿一张还是两张,RT都赢;
……
继续打表就会发现n=2k时总是RT赢,于是判断n是不是2的幂次数就行了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define get(x) scanf("%d", &x)
#define lget(x) scanf("%lld", &x)
#define set(a,b) memset(a, b, sizeof(a))
#define rep(a, b, c) for (int a = b; a <= c; a++)
using namespace std;
const int INF = 0X7F7F7F7F;
int n;
int main()
{
get(n);
if(n & (n-1)) cout << "RJ is winner.";
else cout << "RT is winner.";
return 0;
}
此处用(n&(n-1))来判断n是否是二的幂次数。显然,二进制中2的k次幂等于
不难看出对于每一个n=2k,它与n-1一定每一位都不同,所以用与运算可以很方便的判断n是不是二的幂次数。
这次比赛是真的很简单,但就是因为一些因素导致我没有ak,这个故事告诉我们人不能方,不能乱了阵脚。
评论
还没有任何评论,你来说两句吧!