ABC 151 详细题解

因为本蒟蒻错过了这场比赛,所以赶紧回来打模拟赛……

题解

C

思路

直接模拟即可,但是要细心!

时间复杂度: O ( n + q ) O(n+q) O(n+q)
预估难度:入门/普及-

代码

#include 
#define int long long
using namespace std;

int n,q,temp,p=0,c=0;
int a[100005],b[100005];

signed main()
{
	cin>>n>>q;
	for (int i=1;i<=q;i++)
	{
		string s;
		cin>>temp>>s;
		
		if (s=="AC")  a[temp]=1;
		else
		{
			if (a[temp]==0)  b[temp]++; 
		}
	}
	for (int i=1;i<=n;i++)
	{
		if (a[i])
		{
			c++;
			p+=b[i];
		}
	}
	cout<<c<<' '<<p<<endl;
	
	return 0;
}

D

思路
初看题目,发现是个图论题?! 千万不能挂掉啊~

我们先开一个四维数组GA,其中 G A [ x 1 ] [ y 1 ] [ x 2 ] [ y 2 ] GA[x1][y1][x2][y2] GA[x1][y1][x2][y2]储存了坐标 ( x 1 , y 1 ) (x1,y1) (x1,y1) ( x 2 , y 2 ) (x2,y2) (x2,y2)的距离。接着我们找两个相邻(行相邻或列相邻)的"."并记录该两点的距离为 1 1 1。然后跑一遍弗雷德( F l o y d Floyd Floyd),最后扫一遍找到最长的最短距离即可。

注意初始化!

时间复杂度: O O O( h 3 h^3 h3 w 3 w^3 w3)
预估难度: 普及/提高-

代码

#include 
#define inf 1000000007
using namespace std;

int n,m,maxv=-1;
char a[25][25];
int GA[25][25][25][25];

int main()
{
	cin>>n>>m;
	memset(a,' ',sizeof(a));
	memset(GA,inf,sizeof(GA));
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)  cin>>a[i][j];
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		{
			if (a[i][j]==a[i][j-1]&&a[i][j]=='.')  GA[i][j][i][j-1]=GA[i][j-1][i][j]=1;
			if (a[i][j]==a[i][j+1]&&a[i][j]=='.')  GA[i][j][i][j+1]=GA[i][j+1][i][j]=1;
			if (a[i][j]==a[i+1][j]&&a[i][j]=='.')  GA[i][j][i+1][j]=GA[i+1][j][i][j]=1;
			if (a[i][j]==a[i-1][j]&&a[i][j]=='.')  GA[i][j][i-1][j]=GA[i-1][j][i][j]=1;
		}
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)  GA[i][j][i][j]=0;
	}
	for (int ki=1;ki<=n;ki++)
	{
		for (int kj=1;kj<=m;kj++)
		{
			if (a[ki][kj]=='#')  continue;
			for (int ii=1;ii<=n;ii++)
			{
				for (int ij=1;ij<=m;ij++)
				{
					if (a[ii][ij]=='#')  continue;
					for (int ji=1;ji<=n;ji++)
					{
						for (int jj=1;jj<=m;jj++)
						{
							if (a[ji][jj]=='#')  continue;
							if (GA[ii][ij][ji][jj]>GA[ii][ij][ki][kj]+GA[ki][kj][ji][jj])
							{
								GA[ii][ij][ji][jj]=GA[ii][ij][ki][kj]+GA[ki][kj][ji][jj];
								GA[ji][jj][ii][ij]=GA[ii][ij][ki][kj]+GA[ki][kj][ji][jj];
							}
						}
					}
				}
			}
		}
	}
	for (int ii=1;ii<=n;ii++)
	{
		for (int ij=1;ij<=m;ij++)
		{
			for (int ji=1;ji<=n;ji++)
			{
				for (int jj=1;jj<=m;jj++)
				{
					if (GA[ii][ij][ji][jj]>n*m)  continue;
					else maxv=max(maxv,GA[ii][ij][ji][jj]);
				}
			}
		}
	}
	cout<<maxv<<endl;
	return 0;
}

E

前言
这是一道不错的数学题,欢迎大家前来拍砖。

思路

对于这类题目有一种套路: 求贡献之和。

但是我们怎么知道这个数对答案的贡献呢?我们只需要将它按升序排序后做一些神仙操作 :

①把第i个数与前面的k-1个数相结合,那么他就成为了最大值;所以它给答案的贡献为 a i × C ( i − 1 , k − 1 ) ai×C(i-1,k-1) ai×C(i1,k1)。注意这里 C ( i − 1 , k − 1 ) C(i-1,k-1) C(i1,k1)表示在第i个数前面的i-1个数中选k-1个数的方案数。

②把第i个数与后面的k-1个数相结合,那么他就成为了最小值;所以它给答案的贡献为- a i ∗ C ( n − i , k − 1 ) ai*C(n-i,k-1) aiC(ni,k1)。注意这里 C ( n − i , k − 1 ) C(n-i,k-1) C(ni,k1)表示在第i个数后面的n-i个数中选k-1个数的方案数。

综上所述,答案就是

Σ ( i = 1 , n ) Σ(i=1,n) Σ(i=1,n) a i ( C ( i − 1 , k − 1 ) − C ( n − i , k − 1 ) ) ai(C(i-1,k-1)-C(n-i,k-1)) ai(C(i1,k1)C(ni,k1))
//本蒟蒻不会LaTeX数学公式,请见谅

时间复杂度: O ( n ) O(n) O(n)
预估难度: 普及+/提高

卡点

①看到组合数与模数了吗?所以要用逆元(相信大家都用得很熟了吧);

开long long。有模数就不用开long long,这话您听谁说的?

代码

#include 
#define int long long
using namespace std;

int n,k,mod=1e9+7,ans;
int a[100005],jc[100005];

int quick_power(int a,int b)
{
	int res=1;
	for (;b;b=b>>1,a=(a*a)%mod)
	{
		if (b&1)  res=(res*a)%mod;
	}
	return res;
}

int ny(int k)
{
	return quick_power(k,mod-2);
}

int C(int n,int k)
{
	if (n<=0||k<0||n<k)  return 0;
	if (n==k||k==0)  return 1;
	if (2*k>n)  k=n-k;
	
	return ((jc[n]*ny(jc[n-k]))%mod*ny(jc[k]))%mod;
}

int init()
{
	jc[0]=1;
	for (int i=1;i<=100000;i++)  jc[i]=(jc[i-1]*i)%mod;
}

signed main()
{
	cin>>n>>k;
	init();
	for (int i=1;i<=n;i++)  cin>>a[i];
	
	sort(a+1,a+n+1);
	
	for (int i=1;i<=n;i++)  ans=((ans+a[i]*(C(i-1,k-1)-C(n-i,k-1)))%mod+mod)%mod;
	cout<<ans<<endl;
	
	return 0;
}

F

本蒟蒻先后使用暴力, 凸包, 二分给尝试了一波,结果都在编完后检查时均把思路否认了o(╥﹏╥)o……

待填坑……

总结

①AC题数: 5(本蒟蒻水平也就这样……)
②5题AC耗时: 1+3+12+30+18=64min

今天晚上还有一场ABC……不管了,打ヾ(◍°∇°◍)ノ゙!!!

你可能感兴趣的:(比赛题解)