正文索引 [隐藏]

这么水的校内赛居然能卡掉五道,真是人间奇葩,能给自己气死。

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

其实到现在也不知道为什么会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,这个故事告诉我们人不能方,不能乱了阵脚。