TT数鸭子
题目
分析
这个看数据的范围很大,因此采用数组字符的形式进行存储,思路就是遍历数组,计算出现的数字的个数,需要注意的是复杂度的问题,降低复杂度的方法可以是将string 类型改为数组类型,同时数组取长度是strlen(a),而string 取长度是a.size(),或者a.length().
代码
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
long long num[11];
int main()
{
int n,k;
scanf("%d %d",&n,&k);
char a[20];
int ans=0;
while(n--){
//cin>>a;
scanf("%s",a);
// cout<<a<<endl;
int t=0;
for(int i=0;i<strlen(a);i++){
num[a[i]-'0']++;
if(num[a[i]-'0']==1){
t++;
}
}
if(t<k) ans++;
memset(num,0,sizeof(num));
}
printf("%d\n",ans);
return 0;
}
ZJM 要抵制宇宙射线
题目
分析
提交的时候错误的地方:
(1)半径的平方算成半径
(2)数据类型,用float 过不去,需要用double
(3)属于优化部分,需要求的是点到其他各个点中距离最大值的最小值,我之前在求最小值的时候将数据存了起来,但是后来觉得没必要直接在第二层循环外更新最小值即可。
代码
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define maxn 1010
struct point{
double x,y;
bool operator < (const point& e)const{
if(x!=e.x) return x<e.x;
else if(y!=e.y) return y<e.y;
else return false;
}
}a[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lf %lf",&a[i].x,&a[i].y);
}
sort(a,a+n);
int i;
int s=-1;
double minn=1e15;
for(i=0;i<n;i++){ //i 到其他点的距离
double tmp=0;
for(int j=0;j<n;j++){
double dis=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
if(tmp<dis){ //取大的
tmp=dis;
}
}
if(tmp<minn){
minn=tmp;
s=i;
}
}
printf("%.2lf %.2lf\n",a[s].x,a[s].y);
printf("%.2lf\n",minn);
}
宇宙狗的危机
题目
分析
这道题在测试的时候一心想的是,找公因数有相同的直接连然后计算不同公因数直接的桥梁,然后连接,中间还涉及到缩点之类的想法,然后直接被想法劝退,然后只做了这个思路的第一步,只要任意点都有它的同伴就可以,当然这样思路漏洞是很明显的,没想到这样还能过5个点,美滋滋.直到下来看别人的思路才是一种恍然大悟的感觉,本身二叉搜索树就存在左子树右子树这样的子结构。然后联系gcd 就是连接条件,这样就用动态规划,区间dp.
其中L[i][j]指,以j 为根,区间[i,j-1]为j 的左儿子
R[i][j]指以i 为根,区间[i+1,j]作为i的右儿子。
设k为区间[l,r]的根,
如果L[l][k]=1且r[k][r]=1,则该状态合法,可以转移;
同时l1且rn则说明存在一颗以K为根的平衡二叉树。
如果k与l-1 存在大于1的公因数,那么可以拓展一位以l-1为根,[l,r]为右儿子
如果k与r+1存在大于1的公因数,同样拓展一位以r+1为根,[l,r]为左儿子
初始化的时候是两层循环遍历判断f[i][j]的状态,L和R 在输入的时候初始化,只有根。
代码
#include<stdio.h>
#include<string.h>
using namespace std;
#define maxn 710
int L[maxn][maxn],R[maxn][maxn],f[maxn][maxn],a[maxn];
int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(f,0,sizeof(f));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
L[i][i]=1,R[i][i]=1;
} //输入数据完毕
//区间dp
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(gcd(a[i],a[j])>1){
f[i][j]=f[j][i]=1;
}
}
}
bool flag=false;
for(int l=n;l>=1;l--)
{ //左边
for(int r=1;r<=n;r++ ){ //右边
for(int k=1;k<=r;k++){
if(L[l][k]&&R[k][r])//左右区间可以合并
{
if(l==1&&r==n){
printf("Yes\n");
flag=true;
break;
}
if(f[l-1][k]) R[l-1][r]=1;
if(f[k][r+1]) L[l][r+1]=1;
}
}
}
}
if(!flag)
printf("No\n");
}
}