文章目錄
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();
}
}