第三次线上赛小结

一、星号阵列-18

描述

输入一个不小于6的偶数,输出如下星号阵列。周围一圈是*;正中间两横两竖是+;然后四个角落根据方位,按照类似坐标系的象限,输出1、2、3、4。

例如输入8时,应输出:

输入

只有一组案例。

一个正整数n,表示阵列的宽度和高度。(6<=n<=50)

输出

根据要求输出阵列,阵列的最后一行结束后也有换行。

样例输入

12

样例输出

关键代码

****
for (int i = 1; i <= n; i++)
{
	for (int j = 1; j <= n; j++)
	{
		if (i == 1 || i == n || j == 1 || j == n)
			cout << "*";
		else if (i == n / 2 || i == n / 2 + 1 || j == n / 2 || j == n / 2 + 1)
			cout << "+";
		else if (i<n / 2 && j>n / 2 + 1)
			cout << 1;
		else if (i < n / 2 && j < n / 2)
			cout << 2;
		else if (i > n / 2 + 1 && j < n / 2)
			cout << 3;
		else if (i > n / 2 + 1 && j > n / 2 + 1)
			cout << 4;
	}
	cout << endl;
}

注意事项

通过规律可以看出 第一行、最后一行、第一列、最后一列输出星号,中间两行和中间两列输出加号,然后根据分开的四个位置分别输出四个象限。

二、简易算24点

描述

有4个正整数,要求在不改变数字顺序、不添加括号的前提之下,在每两个数字之间添加一个加法+或者乘法*运算符,凑成一个完整的运算表达式,使得表达式的运算结果为24。

已知这4个正整数,问可以凑出多少种不同的满足要求的表达式?

输入

多组案例。一个正整数n,表示案例的数量。(n<=200000)

每组案例由4个不大于20的正整数组成。

输出

针对每组案例,输出一个整数,表示有多少种不同的满足条件的表达式。

每组案例输出完都要换行。

样例输入

3
2 2 2 3
2 2 2 2
1 2 3 18
 

样例输出

1

0

2

关键代码

********
if(a+b+c+d==24)
    cnt++;
if(a+b+c*d==24)
    cnt++;
if(a+b*c+d==24)
    cnt++;
if(a*b+c+d==24)
    cnt++;
if(a+b*c*d==24)
    cnt++;
if(a*b*c+d==24)
    cnt++;
if(a*b+c*d==24)
    cnt++;
if(a*b*c*d==24)
    cnt++;
********

注意事项

八个可能,暴力就完事。

三、带分数

描述

以一个假分数的形式,输入一个分数的分子和分母部分,要求输出为带分数形式,并且应当正确约分。

例如输入10 8,应输出1+1/4,因为10/8=1+1/4。

如果带分数的整数部分为0,那么只要输出其分数部分。

例如输入2 8,应输出1/4,因为2/8=1/4。

如果带分数的分数部分为0,那么只要输出其整数部分。

例如输入16 8,应输出2,因为16/8=2。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例由两个正整数a和b组成,表示分数的分子和分母。(均不大于1e+8)

输出

针对每组案例,输出带分数形式的分数,具体要求见【问题描述】。

每组案例输出完要换行。

样例输入

3
10 8
2 8
16 8
 

样例输出

1+1/4

1/4

2

关键代码

*********
int gcd(int a, int b)//最大公约数(辗转相除法)
{
    return b > 0 ? gcd(b, a % b) : a;
}
********
int c = a / b;
a = a - c * b;
if (a == 0)
	cout << c << endl;
else
{
	int x = gcd(a, b);
	a = a / x, b = b / x;
	if (c == 0)
		cout << a << "/" << b << endl;
	else
		cout << c << "+" << a << '/' << b << endl;
}

注意事项

化为最简分数需要用到寻找最大公约数的函数,c是带分数的整数部分,然后a和b就变成了一个真分数,a,b可能不是最简分数,所以寻找a,b的最大公约数,a,b同时除最大公约数就是最简分数。

四、直线关系

描述

已知平面直角坐标系的两条直线ax+by+c=0,dx+ey+f=0,问这两条直线的关系是重合、平行还是相交?

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例由6个整数a、b、c、d、e、f组成(绝对值均不大于10000)

输出

针对每组案例,如果两直线重合,则输出1;如果两直线平行,则输出2;如果两直线相交,则输出3。

每组案例输出完要换行。

样例输入

2
1 2 3 4 5 6
1 1 1 1 1 1
 

样例输出

3

1

关键代码

********
int D = a1 * b2 - b1 * a2;
int Dx = (-c1) * b2 - b1 * (-c2);
int Dy = a1 * (-c2) - (-c1) * a2;
if (D != 0)
	cout << 3 << endl;
else
{
	if (Dx != 0 || Dy != 0)
		cout << 2 << endl;
	else if (Dx == 0 & Dy == 0)
		cout << 1 << endl;
}

注意事项

通过行列式求解

通过高中的一般式和斜截式的方法判断直线关系都有缺陷

 五、覆盖范围

描述

已知一个无穷数列的首项是a,从第二项开始,每项是前一项乘b加c后,除以d的余数。问这个数列能够生成多少个不同的数字。

输入

多组案例。一个正整数n,表示案例的数量。(n<=100)

每组案例由4个正整数a、b、c、d组成。(均不大于10000)

输出

针对每组案例,输出一个整数,表示这个无穷数列能生成不同数字的个数。

每组案例输出完要换行。

样例输入

2
1 1 1 10
1 1 2 10
 

样例输出

10

5

关键代码

*******
int sz[10001] = { 0 };
int x = a;
sz[a]++;
while (1)
{
	x = (x * b + c) % d;
	sz[x]++;
	if (sz[x] > 1)
		break;
}
int ans = 0;
for (int i = 0; i < 10001; i++)
{
	if (sz[i] > 0)
	{
		ans++;
	}
}
*************

注意事项

sz数组是用来储存出现过的数字,由题意可知 最后的数列一定是周期数列所以一有一个数重复出现,就表明进入了下一个周期,就能判断一共出现了多少个不一样的数字。

六、哪类更多

描述

将正整数根据其因子的数量分类,例如18有1、2、3、6、9、18这6个因子,那么称18为“6类整数”。

把所有a~b之间的整数(含a和b)按照以上原则分类,问哪类整数的数量最多?有多少个?

输入

多组案例。一个正整数n,表示案例的数量。(n<=20)

每组案例由两个正整数a和b组成。(1<=a<=b<=1e+7)

输出

针对每组案例,输出两个整数x和y,其中x表示数量最多的是x类整数,y表示该类整数的数量。

如果遇到多类整数并列最多,则输出其中最小的x值。

x和y之间要有一个空格。

每组案例输出完要换行

样例输入

2
6 8
4 5
 

样例输出

4 2

2 1

关键代码

*********
for (int i = 1; i < 1e+7; i++)
{
	for (int j = i; j <= 1e+7; j += i)
	{
		factorCnt[j]++;
	}
}
int n;
cin >> n;
while (n--)
{
	int type[450] = { 0 };
	int a, b;
	cin >> a >> b;
	int  Max = -1, pos;
	for (int i = a; i <= b; i++)
	{
		type[factorCnt[i]]++;
		if (type[factorCnt[i]] > Max)
		{
			Max = type[factorCnt[i]];
			pos = factorCnt[i];
		}
		else if (type[factorCnt[i]] == Max && factorCnt[i] < pos)
			pos = factorCnt[i];
    }
}
**************

注意事项

用传统方法找因数肯定会超时,所以要用筛的方法,例如1 是所有数的因数 ,factorCnt的所有数加一,2是所有偶数的因数 factorCnt[偶数]加一……以此类推。(实测运行时间为1500ms差不多)

然后就是Type数组是储存factorCnt[i]类整数的个数,实测最大的因数个数是448 数字是8648640(可能还有别的数字也有这么多因数),所以type数组只要开449(强迫症患者开了450)就行。

然后就是寻找数量最多的n类整数和整数个数,要注意如果遇到多类整数并列最多,则输出其中最小的x值。

2019工控安全比赛线上赛第一场的modbus题目是一个经典的工控安全问题。Modbus是一种常用的工业通信协议,广泛应用于工控系统中。在这个题目中,参赛者需要针对给定的modbus通信流量进行分析和攻击。 首先,参赛者需要分析给定的modbus通信流量,了解通信协议的基本结构和字段含义。通常,modbus协议包含发送方地址、功能码、数据域和错误检测等字段。 接着,参赛者需要从通信流量中发现潜在的安全问题。例如,可能存在未经授权的访问、恶意数据注入、数据篡改等问题。通过仔细观察通信流量以及对协议规范的理解,参赛者可以发现一些异常行为。 在攻击阶段,参赛者需要设计和实施各种攻击方法来利用发现的漏洞。例如,可以尝试发送伪造的modbus请求,以获取未经授权的数据或执行非法操作。也可以尝试发送恶意数据来破坏设备或干扰正常的系统运行。 参赛者在攻击中需要注意保护自身的隐私和安全,以避免被反制或被发现。同时,他们还需要掌握适当的攻击技巧和工具,以增加攻击的效果和成功率。 最后,在比赛结束后,参赛者需要提交详细的攻击报告,其中包括攻击过程、攻击方法和攻击效果的详细描述。同时,参赛者还需要提供相应的解决方案来修复发现的漏洞,以提高工控系统的安全性。 通过这场modbus题目的比赛,参赛者不仅可以提高对工控系统的理解和熟练度,还能够加深对工控安全的认识和思考。这对于提升工控系统的安全性,保护重要设备的稳定运行具有重要意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值