TT数鸭子
解题思路
对于这个问题,简单来说就是求一个数中不同数字的个数,输出那些不同数字个数小于k的所有数字个数,并且不同的数字个数最大为10,所以当k大于10时,所有的数字都满足要求,直接输出n即可,其是这道题不难,当时我在讨论k大于10时,直接输出n,而没有将其余的n个数字进行输出,从而re,痛失好几十分
代码
#include<iostream>
#include<stdio.h>
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要抵御宇宙射线
解题思路
对于这个题,由于n的数据范围不是很大,我们可以枚举每一个点,然后对于每一个点,遍历其余所有的点,找到其与最远点的距离作为以该点为圆心的半径,然后对于每一个点都这样做,然后根据题目要求进行排序,输出排序后数组的第一个元素,复杂度是n^2,是可行的。对于这个题,半径是大于int的范围的,所以要用long long来存,当时少写了一个long long,痛失几十分。
代码
#include<iostream>
#include<cmath>
#include<algorithm>
#include <iomanip>
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;
}
宇宙狗的危机
解题思路
对于这个题,本以为是利用二叉搜索树来解,但是由于输入的数据是有序的,看了大佬的解法原来这是一道区间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<iostream>
#include<string.h>
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;
}
}