题目均来源于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;
}