A题:Flag of Berland CodeForces

[链接]https://vjudge.net/problem/CodeForces-837B

题意:

  • 问:一面旗子是否是由一条长度宽度相同的,并且以字母B G R组成的条纹。在旗子中所出现的条纹样式只有一种,条纹可以是竖向也可以是横向的。类似于俄罗斯国旗,是的话,输出YES;否的话,输出NO。

思路:

  • 首先通过题意,我们可以知道条纹必定是由B G R三种字母按比例组成的,也就说当条纹无法被3整除时,必然输出NO。
  • 其次因为旗子的条纹只有一种且能被3整除,所以将条纹按比列推算,由此,我们可以得到以下图片 alt
  • 因此我们只需要通过判断s[0],s[d],s[2*d]这三条行首是否是不相同的,如果存在相同,就说明该条纹不是按比例构成
  • 然后再将其余每行每列的点与行首相比较,如果存在不同,就说明条纹不符合要求,能运行就说明条纹成立,以下是完整判断条件部分的代码
bool check(int n,int m){
	if (n%3)return false;
	int d=n/3;
	if (s1[d][0]==s1[0][0] || s1[d*2][0]==s1[0][0] || s1[d][0]==s1[d*2][0])return false;
    //只要行首有一个相同,就退出循环
	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			if (s1[i][j] != s1[i/d*d][0])return false;
            //每个点位与行首判断,i/d时会被除为整数,再相乘就可以得到当前位置的行首
		}
	}
	return true;
}
  • 这里使用bool类型的原因是因为我们要做两次判断,一次是原代码位置,一次是翻转90度后,判断点位。
cin >>n>>m;
	for (int i=0;i<n;i++)cin >>s1[i];//读取地图
	if (check(n,m))return cout <<"YES\n",0;//第一次判断
	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)s2[j][i]=s1[i][j];
        //因为在check中使用的是s1数组进行判断,所以需要s2数组记录,再返回给s1数组
	}
	swap(n,m);//交换n,m的位置n==原m,m==原n
	for (int i=0;i<n;i++)
	{
		for (int j=0;j<m;j++)
		{
			s1[i][j]=s2[i][j];
		}
	}
	if (check(n,m))return cout <<"YES\n",0;
	cout <<"NO\n";
  • 两者结合就是ac代码

D题:Hossam and Combinatorics

[链接]:https://vjudge.net/problem/CodeForces-1771A

题意:

  • 问:有t组数据,每次给你n个数,求有几种数的组合可以使|a-b|大于等于其他任意一种组合

思路:

  • 这题考验的是数学思维,要使两个数的差最大,就是要找最大值和最小值,数据n的范围是2e5完全可以用sort排序来找最大值和最小值,之后只要遍历一遍循环,判断是否有数与最大值和最小值相等,就可以得到最大值和最小值的个数
  • 在拿到这两个个数后,为了方便理解,我这里使用第一个样例的第二个数作图: alt
  • 由于是绝对值,所两种位置是可以互换的所以排列后的个数乘以2,这样应该就可以明白了,当最大值和最小值不同的时候,答案就是最大值的个数和最小值个数的乘积再乘以2。
  • 注意是不同的时候,当最大值和最小值相同的时候,显然不会是值之间的相互组合,因为不管怎么组合都会是0,所以每个数的组合方式都会是所有除自己以外的数,即n-1,因为有个n数,所以当这种情况时,答案为n*(n-1)

以下是AC代码:

cin >>t;
	while(t--)
	{
		cin >>n;
		topx=0;
		topy=0;
		for (int i=0;i<n;i++)cin >>a[i];
		sort(a,a+n);
		maxn=a[n-1];
		minn=a[0];
        //第一种情况,最大值和最小值相同时
		if (maxn==minn)
		{
			cout <<1LL*n*(n-1)<<"\n";
            //因为a数组的数据范围是1e5,所以乘以1LL,将int转化为long long 类型,避免爆int
			continue;
		}
        //记录最大值和最小值的个数
		for (int i=0;i<n;i++)
		{
			if (maxn==a[i])topx++;
			if (minn==a[i])topy++;
		}
		cout <<1LL*topx*topy*2<<"\n";
	}