csp第四次模测

文章目录

  • TT数鸭子
    • 解题思路
    • 代码
  • ZJM要抵御宇宙射线
    • 解题思路
    • 代码
  • 宇宙狗的危机
    • 解题思路
    • 代码

TT数鸭子

csp第四次模测_第1张图片csp第四次模测_第2张图片

解题思路

对于这个问题,简单来说就是求一个数中不同数字的个数,输出那些不同数字个数小于k的所有数字个数,并且不同的数字个数最大为10,所以当k大于10时,所有的数字都满足要求,直接输出n即可,其是这道题不难,当时我在讨论k大于10时,直接输出n,而没有将其余的n个数字进行输出,从而re,痛失好几十分

代码

#include
#include
using namespace std;
long long int alln[1000010];
int main()
{
	int n,k;
	cin>>n>>k;
	if(k>10)
	{//k>10 都满足,输出n
		for(int i=0;i<n;i++)
			scanf("%lld",&alln[i]);
		cout<<n<<endl;
	}
	else if(k==1)
	{
		for(int i=0;i<n;i++)
			scanf("%lld",&alln[i]);
		cout<<"0"<<endl;	//k=1所以都不满足,输出0
	} 	
	else
	{
		for(int i=0;i<n;i++)
			scanf("%lld",&alln[i]);
		int a[10],ans=0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<10;j++)
				a[j]=0;
			while(alln[i]>=10)
			{
				int temp=alln[i]%10;
				a[temp]++;//找到一个数的每一位
				alln[i]/=10;
			}
			a[alln[i]]++;
			int flag=0;
			for(int j=0;j<10;j++)
			{
				if(a[j]!=0)
					flag++; 
			}
			if(flag<k)//判断不同数字个数是否小于k
				ans++;	
		}
		cout<<ans<<endl;
	}
	return 0;
 }

ZJM要抵御宇宙射线

csp第四次模测_第3张图片csp第四次模测_第4张图片

解题思路

对于这个题,由于n的数据范围不是很大,我们可以枚举每一个点,然后对于每一个点,遍历其余所有的点,找到其与最远点的距离作为以该点为圆心的半径,然后对于每一个点都这样做,然后根据题目要求进行排序,输出排序后数组的第一个元素,复杂度是n^2,是可行的。对于这个题,半径是大于int的范围的,所以要用long long来存,当时少写了一个long long,痛失几十分。

代码

#include
#include
#include
#include 
using namespace std;
struct point{
	long long int x,y,rad;//一个点的坐标,以这个点为圆心的半径
	bool operator < (const point p)const{//重载小于号
		if(rad!=p.rad)
			return rad<p.rad;
		else if(x!=p.x)	
			return x<p.x;
		else 
			return y<p.y;
	}
	point()
	{
		x=y=0;
		rad=-1;
	}
};
point allp[1010];
int n;
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>allp[i].x>>allp[i].y;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{//枚举每一个点
			if(i!=j)
			{
				long long int temp=pow(allp[i].x-allp[j].x,2)+pow(allp[i].y-allp[j].y,2);
				if(temp>allp[i].rad)
					allp[i].rad=temp;
			}
		}
	}
	sort(allp,allp+n);//排序后输出第一个元素
	cout<<allp[0].x<<".00 "<<allp[0].y<<".00"<<endl;
	cout<<allp[0].rad<<".00";
	return 0;
 }

宇宙狗的危机

csp第四次模测_第5张图片csp第四次模测_第6张图片csp第四次模测_第7张图片csp第四次模测_第8张图片

解题思路

对于这个题,本以为是利用二叉搜索树来解,但是由于输入的数据是有序的,看了大佬的解法原来这是一道区间dp。
首先使用一个二维数组f[i][j]来表示区间[i,j]的数字能否组成一个合法的二叉搜索树,如果可以,则为1,。则最后的结果就判断f[1][n]是否为1即可。使用一个二维数组l[i][j]表示以j对应的数为根,j的左子树为到i的数,这样的二叉搜索树是否存在,使用一个二维数组r[i][j]表示以i对应的数为根,i的右子树为到j的数,这样的二叉搜索树是否存在。还用了一个数组com[i][j],来表示点i和j所对应的数的gcd是否大于1,如果大于1,该值为1,否则为0。然后进行状态转移,一共进行三层循环,第一层为所有点,第二层为区间的左端点和右端点,第三层是枚举的根节点,在左端点和右端点之间。如果l[a][k]=1并且r[k][b]=1,那么区间[a,b]一定可以组成一个二叉搜索树。如果此时com[k][a-1]为1,那么k可以做a-1的右孩子,则r[a-1][b]=1,同理,如果com[k][b+1]为1,那么k可以做b+1的左孩子,则l[a][b+1]=1。

代码

#include
#include
using namespace std;
int gcd(int a,int b)
{//计算gcd
	return b==0?a:gcd(b,a%b);
} 
int alln[710],com[710][710],l[710][710],r[710][710],f[710][710];
int main()
{
	int T;
	cin>>T;
	for(int t=0;t<T;t++)
	{
		int n;
		cin>>n;
		memset(l,0,sizeof(l));
		memset(r,0,sizeof(r));
		memset(f,0,sizeof(f));
		memset(com,0,sizeof(com));
		for(int i=1;i<=n;i++)
		{
			cin>>alln[i];
			l[i][i]=r[i][i]=1;//初始化
		}
			
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int te=gcd(alln[i],alln[j]);
				if(te>1)//计算每两个数的gcd
					com[i][j]=1;
			}
		}
		for(int i=1;i<=n;i++)
		{//枚举所有数
			for(int l1=1,r1=l1+i-1;r1<=n;l1++,r1++)
			{//枚举左右区间
				for(int k=l1;k<=r1;k++)
				{//枚举区间中的根
					if(l[l1][k]==1&&r[k][r1]==1)
					{//如果k为根可行,则更新
						f[l1][r1]=1;
						if(com[k][l1-1])
							r[l1-1][r1]=1;//k为l1-1的右孩子可行
						if(com[k][r1+1])
							l[l1][r1+1]=1;//k为r+1的左孩子可行
					}
				}
			}
		}
		if(f[1][n]==1)
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;
	}
} 

你可能感兴趣的:(csp第四次模测)