计科院20201011蓝桥训练题解

题目均来源于dotcpp
bin巨出的题就是难啊啊啊

A 拼接平方数

小明发现49很有趣,首先,它是个平方数。它可以拆分为4和9,拆分出来的部分也是平方数。169也有这个性质,我们权且称它们为:拼接平方数。
100可拆分1 00,这有点勉强,我们规定,0 00 000 等都不算平方数。
小明想:还有哪些数字是这样的呢?
你的任务出现了:找到某个区间的所有拼接平方数。
输入
两个正整数 a b (a<b<10^6)
输出
若干行,每行一个正整数。表示所有的区间[a,b]中的拼接平方数
样例输入
1 200
样例输出
49
169

思路:有以下几点需要注意:
1、首先这个数要满足是平方数。
2、某个数就拆分成两个数就行了!!!不会出现拆分成三个数以上的情况
3、所以挨个枚举遍历即可。

注意 9025这样的数也算(9 025就是25)
下面是AC代码

const int maxn=1e6+10;
int a,b;
bool con[maxn];
bool judge(int i){
    int d=1;
    while(1){
        int num1=i/d;
        if(num1==0) return false;
        int num2=i%d;
        if(con[num1]&&con[num2]) return true;
        else{
            d*=10;
        }
    }
}
int main() {
    cl(con,false);
    rep(i,1,1000) con[i*i]=true;
    sdd(a,b);
    rep(i,a,b){
        if(con[i]&&judge(i)) printf("%d\n",i);
    }
	return 0;
}

B 合根植物

w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
输入
第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
接下来一行,一个整数k,表示下面还有k行数据(0<k<100000)
接下来k行,第行两个整数a,b,表示编号为a的小格子和编号为b的小格子合根了。

思路:并查集,不需要搜索。并查集就行了。
下面是AC代码 注意数组要开到1e6!!!!

const int maxn=1000010;
int n,m,k,cnt;
int pre[maxn];
bool con[maxn];
set<int> st;
inline int id(int i,int j){
    return m*(i-1)+j;//1开始
}
int find(int x){
    if(x==pre[x]) return x;
    return pre[x]=find(pre[x]);
}
void join(int a,int b){
    int fa=find(a),fb=find(b);
    pre[fa]=fb;
}
void init(){
    rep(i,1,m*n){
        pre[i]=i;
        con[i]=false;
    }
    st.clear();
}
int main() {
    sddd(n,m,k);
    init();
    rep(i,1,k){
        int u,v;
        sdd(u,v);
        join(u,v);
    }
    rep(i,1,n){
        rep(j,1,m){
            con[find(id(i,j))]=true;
        }
    }
    int cnt=0;
    rep(i,1,m*n){
        if(con[i]) cnt++;
    }
    printf("%d\n",cnt);
	return 0;
}

C 修改数组

题目描述
给定一个长度为 N 的数组 A = [A1, A2, · · · AN ],数组中有可能有重复出现 的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。

当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则 小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直 到 Ai 没有在 A1 ∼ Ai−1 中出现过。

当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。 现在给定初始的 A 数组,请你计算出最终的 A 数组

输入
第一行包含一个整数 N。 第二行包含N个整数A1,A2,··· ,AN

输出
输出N个整数,依次是最终的A1,A2,··· ,AN。

样例输入
5
2 1 1 3 4
样例输出
2 1 3 4 5

思路:直接模拟会T 亲测。
要用并查集!!!竟然要用并查集!!!
下面是关键代码。

	rep(i,1,1000000) pre[i]=i;
    rep(i,1,n){
        sd(a[i]);
        int tp=find(a[i]);
        a[i]=tp;
        pre[a[i]]=find(tp+1);
    }

解释:先把所有的pre i 置 i
然后对于每一个a[i] 都看看当前的祖先是谁,然后自己就是当前的祖先
然后因为这个已经用过了 就让当前这个置tp+1为祖先。
挺巧妙的!!!
自己没想到真的没想到!!!
下面是AC代码

using namespace std;
const int maxn=1e5+10;
int n;
int a[maxn];
int pre[maxn*10];
int find(int x){
    if(x==pre[x]) return x;
    return pre[x]=find(pre[x]);
}
int main() {
    sd(n);
    rep(i,1,1000000) pre[i]=i;
    rep(i,1,n){
        sd(a[i]);
        int tp=find(a[i]);
        a[i]=tp;
        pre[a[i]]=find(tp+1);
    }
    rep(i,1,n){
        printf("%d%c",a[i],i==n?'\n':' ');
    }

	return 0;
}

D 补刀

当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低,就会被击杀。为了获得经验,UIM 希望在防御塔将这个小兵杀死之前,亲自补刀将其击杀。

为了简化问题,我们假设这个小兵有 h 点的生命值。每次防御塔的攻击可以给小兵造成 x 点伤害,而你的英雄每次攻击可以给小兵造成 y 点伤害。你的攻击速度和防御塔攻击速度相同,所以你可以在防御塔第一次攻击小兵之前,或者每次防御塔攻击之后,选择是否对小兵进行一次攻击,当然你也可以选择不攻击。

现在想知道,给出这些信息,判断英雄是否有办法将这个小兵击杀?

输入

每个测试点由多组数据组成。

输入第一行,包含一个正整数 T,表示数据组数。

接下来 T 行,每行三个非负整数 h,x,y,其意义已经在题目描述中给出。

输出
输出 T 行。对于每组数据,如果可以最后将小兵击杀,输出 Yes 否则输出 No

样例输入
5
100 100 1
100 97 1
100 98 1
100 99 1
100 100 0
样例输出
No
No
Yes
Yes
No

思路:
1、先考虑x=0或者y=0或者y>=h的情况 特判
2、否则计算出塔要打m次(还不能让塔打完 如果整除了要剩一点)
3、然后判断 人再打m+1次能不能打完h (直接判断最大的 自己看的题解从1开始加 莫名其妙的真的是

下面是AC代码:

using namespace std;
int main() {
    int T;
    sd(T);
    while(T--){
        ll h,x,y;
        cin>>h>>x>>y;
        if(y==0){
            printf("No\n");
            continue;
        }else if(x==0||y>=h){
            printf("Yes\n");
            continue;
        }
        bool flag=false;
        ll num=h/x;
        if(h%x==0) num--;
        if(num*x+(num+1)*y>=h) flag=true;
        if(flag) printf("Yes\n");
        else printf("No\n");
    }
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值