A题:Flag of Berland CodeForces
[链接]https://vjudge.net/problem/CodeForces-837B
题意:
- 问:一面旗子是否是由一条长度宽度相同的,并且以字母B G R组成的条纹。在旗子中所出现的条纹样式只有一种,条纹可以是竖向也可以是横向的。类似于俄罗斯国旗,是的话,输出YES;否的话,输出NO。
思路:
- 首先通过题意,我们可以知道条纹必定是由B G R三种字母按比例组成的,也就说当条纹无法被3整除时,必然输出NO。
- 其次因为旗子的条纹只有一种且能被3整除,所以将条纹按比列推算,由此,我们可以得到以下图片
- 因此我们只需要通过判断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排序来找最大值和最小值,之后只要遍历一遍循环,判断是否有数与最大值和最小值相等,就可以得到最大值和最小值的个数
- 在拿到这两个个数后,为了方便理解,我这里使用第一个样例的第二个数作图:
- 由于是绝对值,所两种位置是可以互换的所以排列后的个数乘以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";
}