CSP M4

A - TT数鸭子

这一天,TT因为疫情在家憋得难受,在云吸猫一小时后,TT决定去附近自家的山头游玩。
TT来到一个小湖边,看到了许多在湖边嬉戏的鸭子,TT顿生羡慕。此时他发现每一只鸭子都不 一样,或羽毛不同,或性格不同。TT在脑子里开了一个map<鸭子,整数> tong,把鸭子变成了 一些数字。现在他好奇,有多少只鸭子映射成的数的数位中不同的数字个数小于k。

输入

输入第一行包含两个数n,k,表示鸭子的个数和题目要求的k。
接下来一行有n个数,ai每个数表示鸭子被TT映射之后的值。

输出

输出一行,一个数,表示满足题目描述的鸭子的个数。
无行末空格

样例输入

6 5
123456789 9876543210 233 666 1 114514

样例输出

4

思路

是一道简单的思维题。
因为输入的数据量级非常大,可能会爆精度;
介于仅仅用到每一位上数据大小,仅是属于0~9,所以用字符串来接收这一个数据,然后对每一位数据进行处理;

剪枝

因为K>=11的时候,无论什么数据都能够符合条件,所以这时候,直接输出数据数量即可;

注意

数据量有点大,用scanf来处理输入的问题;否则会超时;

代码

#include <iostream>
#include <cstring>

using namespace std;
int n,k;
string s;
int cnt;
int duck[15];

int main(){
	ios::sync_with_stdio(false);
	cnt = 0;
	cin>>n>>k;
	s.clear();
	for(int i=0;i<n;i++){
		cin>>s;
		//剪枝
		if(k>=11){
			cnt++;
			continue; 
		}	
		
		memset(duck,0,sizeof(duck));
			
		int tot=0;
		bool flag = false;
		//判断数据位数据大小问题
		for(int i=0;i<s.size();i++){
			int number = s[i] - '0';
			duck[number]++;
			if(duck[number]==1)tot++;
			if(tot>=k){
				flag = true;
				break;
			}
		}
		if(!flag)
		cnt++;
		
	}
	cout<<cnt<<endl;
	return 0;
}

B - ZJM要抵御宇宙射线

据传,2020年是宇宙射线集中爆发的一年,这和神秘的宇宙狗脱不了干系!但是瑞神和东东忙于正面对决宇宙狗,宇宙射线的抵御工作就落到了ZJM的身上。
假设宇宙射线的发射点位于一个平面,ZJM已经通过特殊手段获取了所有宇宙射线的发射点,他们的座标都是整数。而ZJM要构造一个保护罩,这个保护罩是一个圆形 ,中心位于一个宇宙射线的发射点上。同时,因为大部分
经费都拨给了瑞神,所以ZJM要节省经费,做一个最小面积的保护罩。当ZJM决定好之后,东东来找ZJM一起对抗宇宙狗去了,所以ZJM把问题扔给了你~

输入

输入第一行一个正整数N,表示宇宙射线发射点的个数
接下来N行,每行两个整数X,Y,表示宇宙射线发射点的位置

输出

输出包括两行
第一行输出保护罩的中心座标x,y用空格隔开
第二行输出保护罩半径的平方
(所有输出保留两位小数,如有多解,输出x较小的点,如还有多解,输入y较小的点)
无行末空格

样例输入

5
0 0
0 1
1 0
0 -1
-1 0
1
2
3
4
5

样例输出

0.00 0.00
1.00

思路

综述

是CSPT2的难度,考察不到算法的问题,直接暴力就可以解决问题;
遍历每一个点,对每一个点找出距离它最远的一个,这就是半径。
在所有的半径中找出最短的一个;

总结

一开始读错题了,没看到圆的中心是在所有的点集中。
一开始没看到这句话,以为是最小覆盖圆的问题。

最后看到了,就顺利写完了,但是又没看到输出的是半径的平方,直接爆零。

代码

#include <string.h> 
#include <stdio.h>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm> 
#include <iostream>
#include <math.h>
#include <stdlib.h>  
//#define M 1050

const int maxn = 1050;
using namespace std;
int n;
double X,Y;
struct Point
{
    double x,y;
}p[maxn];

struct Circle
{
    Point center;
    double r;
    bool operator < (const Circle & P)const{
		if(r != P.r) return r < P.r;
		else if(center.x != P.center.x)return center.x < P.center.x;
		return center.y < P.center.y;
	}
};
Circle circles[maxn];


double pow(double x)
{
    return x*x;
}


double Len(Point a,Point b)
{
    return sqrt(pow(a.x-b.x)+pow(a.y-b.y));
}


void work(){
	//枚举所有的点,找到合适的就push 
	for(int i=0;i<n;i++){
		
		circles[i].center = p[i];
		circles[i].r = 0;
		int rad = 0 ;
		for(int j=0;j<n;j++){
			if(j==i)continue;
			double rad = Len(p[i],p[j]);
			if(rad > circles[i].r){
				circles[i].r = rad;
			}
		} 
	}
	sort(circles,circles+n);
	printf("%.2lf %.2lf\n%.2lf\n",circles[0].center.x,circles[0].center.y,circles[0].r*circles[0].r);
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>p[i].x>>p[i].y;
	}
	work();
}


C - 宇宙狗的危机

在瑞神大战宇宙射线中我们了解到了宇宙狗的厉害之处,虽然宇宙狗凶神恶煞,但是宇宙狗有一个很可爱的女朋友。
最近,他的女朋友得到了一些数,同时,她还很喜欢树,所以她打算把得到的数拼成一颗树。
这一天,她快拼完了,同时她和好友相约假期出去玩。贪吃的宇宙狗不小心把树的树枝都吃掉了。所以恐惧包围了宇宙狗,他现在要恢复整棵树,但是它只知道这棵树是一颗二叉搜索树,同时任意树边相连的两个节点的gcd(greatest common divisor)都超过1。
但是宇宙狗只会发射宇宙射线,他来请求你的帮助,问你能否帮他解决这个问题。
补充知识:
GCD:最大公约数,两个或多个整数共有约数中最大的一个 ,例如8和6的最大公约数是2。
一个简短的用辗转相除法求gcd的例子:
int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}

输入

输入第一行一个t,表示数据组数。
对于每组数据,第一行输入一个n,表示数的个数
接下来一行有n个数​,输入保证是升序的。

输出

每组数据输出一行,如果能够造出来满足题目描述的树,输出Yes,否则输出No。
无行末空格。

样例输入

1
6
3 6 9 18 36 108
1
2
3

样例输出

Yes
1

思路

综述

这道题是一道区间DP问题。
动态规划的状态定义以及状态转移方程的设置极为重要

状态定义

思路是模仿的,感觉特别巧妙,用了两个二维数组就描述出了状态,并且能够轻松的进行状态的转移;

l[i][j]表示以i为根i-1到j为i的右子树成立
r[i][j]表示以j为根i到j-1为j的左子树成立
状态转移
if(l[i][k] && r[k][j] && f[i-1][k]) r[i-1][j]=1;
if(l[i][k] && r[k][j] && f[j+1][k]) l[i][j+1]=1;

辗转相除法

定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。
欧几里德算法又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。计算公式gcd(a,b) = gcd(b,a mod b)。

总结

这道题,在考试的时候,因为时间不是很够了,就写了5mins。
应该是测试数据有点水了,我写了一个判定条件,也就是必要不充分条件。
拿了60分。还好对第二题爆零有点安慰。

#include"string.h"
#include"stdio.h"
#include"queue"
#include"stack"
#include"vector"
#include"algorithm"
#include"iostream"
#include"math.h"
#include"stdlib.h"

using namespace std;

int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}

int t,n;
vector<int> num;
const int maxn = 1e5;
int value[maxn];
void work(){
	memset(value,0,sizeof(value));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(j==i)continue;
			if(gcd(num[i],num[j])==1){
				value[i]++;
			}
		}
	}
	for(int i=0;i<n;i++){
		if(value[i]==n){
			cout<<"No"<<endl;
			return;
		}
	}

	cout<<"Yes"<<endl;
}

void init(){
	num.clear();
}
int main()
{

    cin>>t;

    int temp;
    for(int i=0;i<t;i++){
    	init();
    	cin>>n;
    	for(int j=0;j<n;j++){
    		cin>>temp;
    		num.push_back(temp);
		}
    	work();
	}
}

代码

正确代码:

#include <iostream>
#include <cstring>

using namespace std;

const int maxn = 800;

int l[maxn][maxn], r[maxn][maxn];
int f[maxn][maxn];
int t;
int a[maxn];
int n;

int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }

void init()
{
    memset(l, 0, sizeof(l));
    memset(r, 0, sizeof(r));
    memset(f, 0, sizeof(f));
    memset(a,0,sizeof(a));
}

void in()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        l[i][i] = r[i][i] = 1;
    }

    for (int i = 1; i <= n; i++)
    {
        for (int j = i; j <= n; j++)
        {
            if (gcd(a[i], a[j]) > 1)
            {
                f[i][j] = f[j][i] = 1;
            }
        }
    }
}

void work()
{

    for (int i = n; i >= 1; i--)
    {
        for (int j = i; j <= n; j++)
        {
            for (int k = i; k <= j; k++)
            {
                if (l[i][k] && r[k][j])
                {
                    if (f[i - 1][k])
                    {
                        r[i - 1][j] = 1;
                    }
                    if (f[k][j + 1])
                    {
                        l[i][j + 1] = 1;
                    }
                }
            }
        }
    }
//    printf("No\n");
}

void output(){
    for(int k=1;k<=n;k++){
        if(l[1][k] && r[k][n]){
            cout<<"Yes"<<endl;
            return;
        }
    }
    cout<<"No"<<endl;
}

int main()
{
    cin >> t;
    while (t--)
    {
        init();
        in();
        work();
        output();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章