Educational Codeforces Round 115 (Rated for Div. 2)
又是脑瘫的一天,C题想着用商和余数来表示平均数(人太傻了,没办法),还等到WA了一发才发现这是个错误的想法,还是老老实实的用double吧!D一个long long int 没开连WA两发,真实傻到了家。咕咕咕,还是咕出一篇题解来吧!
A - Computer Game
题意:
Monocarp在玩一个游戏,他现在处在一个 2 × n 2\times n 2×n的a矩阵内,如果 a [ i ] [ j ] = 1 a[i][j]=1 a[i][j]=1则说明该位置不能行走,他当前在(1,1)这个位置,问他是否能走到(2,n)这个位置上。每一次行走只能往周围8个方向。
思路:
只需要判断是否存在 a [ 1 ] [ j ] = a [ 2 ] [ j ] = 1 a[1][j]=a[2][j]=1 a[1][j]=a[2][j]=1,如果存在的话则说明从j的左边是无法到达右边的,则一定也不能到达(2,n)
参考代码:
#include<bits/stdc++.h>
using namespace std;
char a[3][110];
int n;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=2;i++)
scanf("%s",a[i]+1);
if(a[1][1]=='1'||a[2][n]=='1')printf("NO\n");
else
{
int flag=0;
for(int i=1;i<=n;i++)
{
if(a[1][i]=='1'&&a[2][i]=='1')
{
flag=1;
break;
}
}
if(flag==0)printf("YES\n");
else printf("NO\n");
}
}
// system("pause");
return 0;
}
B - Groups
题意:
一个班有n个人,每一个都对自己的周一到周五都有计划(0代表空闲,1代表忙碌),现在要组织两个活动需要全班人的参与且两个活动不能在同一天,班长计划把班级里的人分成两组(一个人不能同时参加两组),问是否能将班级里的同学根据空闲情况分成两组参加活动。
思路:
以为只有5天,所以可以枚举组织活动的两天进行check即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int a[maxn][8],n;
bool check(int x,int y)
{
int sum=0,sumx=0,sumy=0;
for(int i=1;i<=n;i++)
{
int xx=a[i][x],yy=a[i][y];
if(xx==1&&yy==1)sum++;
else if(xx==1)sumx++;
else if(yy==1)sumy++;
}
int minn=min(sumx,sumy),maxx=max(sumx,sumy);
if(sum<maxx-minn)return false;
else
{
sum-=maxx-minn;
if(sum%2==0)
{
if(2*(maxx+sum/2)==n)return true;
else return false;
}
else return false;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=5;j++)
scanf("%d",&a[i][j]);
}
int flag=0;
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
if(i==j)continue;
if(check(i,j)==true)
{
// cout<<i<<" "<<j<<endl;
flag=1;
break;
}
}
if(flag==1)break;
}
if(flag==1)printf("YES\n");
else printf("NO\n");
}
// system("pause");
return 0;
}
C - Delete Two Elements
题意:
给定一个长度为n的a数组,求出它的平均数k,问存在多少个二元组 ( i , j ) 且 i < j (i,j)且i<j (i,j)且i<j使得删去 a [ i ] 和 a [ j ] a[i]和a[j] a[i]和a[j]后剩下的n-2个数的平均数还是k
思路:
删除两个数后使得剩下的数的平均值仍为k,则删除的两个数的平均值应该为k。假如删去的一个数为x,则另一个不就是 2 × k − x 2\times k-x 2×k−x嘛,则可以记录每一个数的数量,然后枚举x,计算每一个x对答案的贡献求和即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PDD pair<double,double>
const int maxn=2e5+10;
double a[maxn];
int n;
unordered_map<double,ll>mm;
map<PDD,bool>vis;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mm.clear();
vis.clear();
scanf("%d",&n);
double sum=0;
vector<double>v;
for(int i=1;i<=n;i++)
{
scanf("%lf",&a[i]);
v.push_back(a[i]);
sum+=a[i];
mm[a[i]]++;
}
double k=sum/n;
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
ll ans=0;
for(int i=0;i<v.size();i++)
{
double xx=2*k;
if(mm[xx-v[i]]>0&&vis[{v[i],xx-v[i]}]==false&&vis[{xx-v[i],v[i]}]==false)
{
if(v[i]!=xx-v[i])ans+=mm[v[i]]*mm[xx-v[i]];
else
{
ll val=mm[v[i]]-1;
ans+=val*(val+1)/2;
}
vis[{v[i],xx-v[i]}]=true;
vis[{xx-v[i],v[i]}]=true;
}
}
printf("%lld\n",ans);
}
// system("pause");
return 0;
}
D - Training Session
题意:
给定两个长度为n的a、b数组,并且对于任意一对
(
i
,
j
)
不
存
在
a
[
i
]
=
a
[
j
]
并
且
b
[
i
]
=
b
[
j
]
(i,j)不存在a[i]=a[j]并且b[i]=b[j]
(i,j)不存在a[i]=a[j]并且b[i]=b[j],求任选互不相等的(i,j,k)至少满足以下两个条件中一个的三元组个数:
1.
a
[
i
]
、
a
[
j
]
、
a
[
k
]
互
不
相
等
a[i]、a[j]、a[k]互不相等
a[i]、a[j]、a[k]互不相等
2. b [ i ] 、 b [ j ] 、 b [ k ] 互 不 相 等 b[i]、b[j]、b[k]互不相等 b[i]、b[j]、b[k]互不相等
思路:
如果直接求满足条件的方案数是很难求得出来的,所以我们可以求出所有的方案数-不符合要求的方案数。
由题可知,不满足条件的三元组一定是以下形式:
a [ i ] = a [ j ] 且 b [ i ] ! = b [ j ] a[i]=a[j]且b[i]!=b[j] a[i]=a[j]且b[i]!=b[j]
a [ k ] ≠ a [ i ] 且 ( b [ k ] = b [ i ] 或 b [ k ] = b [ j ] ) a[k]\ne a[i]且(b[k]=b[i]或b[k]=b[j]) a[k]=a[i]且(b[k]=b[i]或b[k]=b[j])
这样的话我们可以for循环枚举 a [ i ] 、 b [ i ] a[i]、b[i] a[i]、b[i],然后在第一个数等于a[i]的里面找到 a [ j ] 和 b [ j ] a[j]和b[j] a[j]和b[j],那最后k的所有取值数只能是 b [ k ] = b [ i ] 或 b [ k ] = b [ j ] b[k]=b[i]或b[k]=b[j] b[k]=b[i]或b[k]=b[j]的数量。
假设:
a1=2,b1=4
a2=2,b2=1
a3=2,b3=2
则对于i=1,j=2时b[k]的取值只能是4 和1,所以只需要求出a不等于2且b=4或1的序列的数量则为三元组的贡献。
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int,int>
const int maxn=2e5+10;
unordered_map<int,ll>m1;
unordered_map<int,vector<int>>mp;
ll vis[maxn],n;
PII p[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
m1.clear();
mp.clear();
for(int i=1;i<=n;i++)
{
int l,r;
vis[i]=-1;
scanf("%d%d",&l,&r);
p[i]={l,r};
m1[r]++;
mp[l].push_back(r);
}
ll ans=n*(n-1)*(n-2)/6;
ll sum=0;
for(int i=1;i<=n;i++)
{
int xx,yy;
xx=p[i].first,yy=p[i].second;
if(vis[xx]==-1)
{
ll sum1=0;
for(auto it:mp[xx])
sum1+=m1[it]-1;
vis[xx]=sum1;
}
ll hh=m1[yy]-1;
sum+=hh*(mp[xx].size()-1)+vis[xx]-hh;
}
printf("%lld\n",ans-sum/2);
}
// system("pause");
return 0;
}