NCST 2018-2019秋季学期17级个人排位赛(二)

参考题解Reference Solution



A : Lucky Word

Time Limit:2.000 Sec Memory Limit:128 MiB

Description

小A的英语很差,所以每次做英语选择题时都很头疼,这不快要考四级了,但是他找到了一种方法,经试验证明,用这种方法选择选项的时候选对的几率非常大!
这种方法具体如下:假设\(maxn\)是单词中出现次数最多的字母的出现次数,\(minn\)是单词中出现次数最少的字母的出现次数,如果\(maxn-minn\)是一个质数,那么笨小熊就认为这是个Lucky Word,这样的单词很可能就是正确的答案。

Input

第一行数据\(N(0 < N < 10)\)
每组测试数据输入只有一行,是一个单词,其中只可能出现小写字母,并且长度小于\(100\)

Output

每组测试数据输出共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出Lucky Word,否则输出No Answer
第二行是一个整数,如果输入单词是Lucky Word,输出\(maxn-minn\)的值,否则输出\(0\)



Sample Input

2
error
lucky



Sample Output

Lucky Word
2
No Answer
0



PZ's Solution

1.可以参考NCST 2018-2019秋季学期17级个人排位赛(一) 的B:fzc的爱好;

2.然后,按照题意模拟就可以了;

  • TAG:字符串;质数



PZ.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
string s;
int N,maxn,minn,vis[30];
bool check_prime(int x){
	if(x<=1) return 0;
	for(int i=2;i*i<=x;++i)
		if(i%x==0) return 0;
	return 1;
}
int main(){
	scanf("%d",&N);
	while(N--){
		cin>>s;
		maxn=-INT_MAX; minn=INT_MAX;
		memset(vis,0,sizeof(vis));
		for(int i=0;i<s.size();++i){
			vis[s[i]-'a']++;
			maxn=max(maxn,vis[s[i]-'a']);
			minn=min(minn,vis[s[i]-'a']);
		}
		if(check_prime(maxn-minn)){
			printf("Lucky Word\n%d\n",maxn-minn);
		} else {
			printf("No Answer\n0\n");
		}
	}
	return 0;
}






B : 小A的烦恼

Time Limit:2.000 Sec Memory Limit:128 MiB

Description

刚上大一的小A最近看上了隔壁班的小S,犹豫了段时间后,他终于向小S表白了,但小S并没有立刻答应,而是给了小A一个密码盒子,并告诉小A她想说的话都在盒子里,盒子的密码是由4个数字组成。小A很开心,但令小A烦恼的是他不知道怎么打开这个盒子,虽然盒子上有4个数字,但并不是盒子的密码,他只知道密码的四个数是由盒子上的每个数字在二进制表示里1的个数,可是他没有学过二进制,无法解出密码。看到小A一筹莫展的样子,你能帮他解出盒子的密码吗?

Input

第一行一个整数\(M\),表示测试实例的个数;
后面\(M\)行输入数据,每行包含四个正整数\(a、b、c、d\)
规定:\(1 \leqslant M \leqslant 100\)

Output

每组测试数据输出占一行,输出\(4\)个整数。



Sample Input

2
8 14 16 29
25 127 100 64



Sample Output

1 3 1 4
3 7 3 1



PZ's Solution

1.预处理\(2^0,2^1,2^2,\cdots,2^{30}\)的值;

2.让每个数\(x\)\(2^i\)进行\(\&\)(和)操作,如果\(x\&2^i=2^i\),那么\(x\)在二进制下就有一个\(1\)

  • TAG:二进制



PZ.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int M,P[50],a[5],ans;
int main(){
	scanf("%d",&M);
	P[0]=1;
	for(int i=1;i<=30;++i)
		P[i]=P[i-1]*2;
	while(M--){
		for(int i=1;i<=4;++i) scanf("%d",&a[i]);
		for(int i=1;i<=4;++i){
			ans=0;
			for(int j=0;j<=30;++j){
				if((a[i]&P[j])==P[j])
					++ans;
			}
			printf("%d ",ans);
		}
		puts("");		
	}
	return 0;
}






C : 赛跑

Time Limit:2.000 Sec Memory Limit:128 MiB

Description

小A表白成功后,周末跟小S约好,一起去跑步,小A跟小S比赛,看谁跑的快,并让小S先跑,小S每分钟跑\(X\)米。\(M\)分钟后,小A带着他的宠物狗开始跑,以每分钟\(Y\)米的速度去追小S,而宠物狗以每分钟\(Z\)米的速度向小S跑去,追上小S后,又立即返回,直到小A追上小S时,问宠物狗跑了多少米?

Input

第一行输入一个整数\(N\),表示测试数据的组数\((N<100)\)
每组测试数据占一行,是四个正整数,分别为\(M,X,Y,Z\)(数据保证\(X<Y<Z\)

Output

输出狗跑的路径,结果保留小数点后两位。



Sample Input

1
5 10 15 20



Sample Output

200.00



PZ's Solution

1.小S先跑,\(M\)分钟后,小A带着他的宠物狗开始跑,此时 小S 距离 小A和他的宠物狗 \(X\times M\)米远;

2.设从小A开跑开始, \(T\)分钟后追上小S,可列出方程:

\[Y \times T =X \times T + X \times M \]

可得\(T=\frac{X\times M}{Y-X}\)

3.则可以得到,狗跑的距离(不是位移!!!)为\(Z \times T\)米;

  • TAG:数学



PZ.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N;
double M,X,Y,Z;
int main(){
	scanf("%d",&N);
	while(N--){
		scanf("%lf %lf %lf %lf",&M,&X,&Y,&Z);
		printf("%.2lf\n",Z*X*M/(Y-X));
	}
	return 0;
}






D : Catch My Pet

Time Limit:2.000 Sec Memory Limit:128 MiB

Description

小A的宠物狗最近不听话了,经常乱跑,这不,小A又在找他的宠物狗了,好在小A在宠物狗身上安装了定位器,现在小A知道了宠物狗的位置,要去抓住宠物狗。小A和宠物狗在同一条直线上,小A起始位于点\(N(0 \leqslant N \leqslant 100000)\),宠物狗位于点\(K(0 \leqslant K \leqslant 100000)\)。小A有以下两种移动方式。
(1)从\(X\)移动到\(X-1\)\(X+1\),每次移动花费一分钟。
(2)从\(X\)移动到\(2X\),每次移动花费一分钟。
假设宠物狗不知道小A在找他,站在原地不动。那小A最少要花多少时间才能抓住宠物狗?

Input

输入只有一行,\(N\)\(K\)

Output

抓到宠物狗要花到最少时间。



Sample Input

5 17



Sample Output

4



PZ's Solution

1.本题可以参考NCST 2018-2019秋季学期17级个人排位赛(一) 的A:PUBG;

2.将本题视为一个最短路问题,可以发现每条边的边权均为\(1\)

3.考虑使用BFS即可解决,第一次访问到\(k\)的时候,一定为时间消耗最少的情况;

  • TAG:BFS广度优先搜索



PZ.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,k,ans[100005];
bool vis[100005];
queue<int>q;
void bfs(){
	q.push(n); vis[n]=1;
	while(!q.empty()){
		int x=q.front(); q.pop();
		if(x==k) return;
		if(x-1>=0&&!vis[x-1]){
			ans[x-1]=ans[x]+1; 
			q.push(x-1);
			vis[x-1]=1;
		}
		if(x+1<=100000&&!vis[x+1]){
			ans[x+1]=ans[x]+1;
			q.push(x+1);
			vis[x+1]=1;
		}
		if(2*x<=100000&&!vis[2*x]){
			ans[2*x]=ans[x]+1;
			q.push(2*x);
			vis[2*x]=1;
		}
	}
}
int main(){
	scanf("%d %d",&n,&k);
	bfs();
	printf("%d",ans[k]);
	return 0;
}






E : 水池数目

Time Limit:2.000 Sec Memory Limit:128 MiB

Description

小A的学校有一些小河和一些湖泊,现在把它们统一看成水池,小A手里有一张学校某处的地图,这个地图上仅标识了此处是否是水池,小A想知道这块地方有多少个水池,现在,任务交给你了,请编写程序算出该地图中有几个水池。

Input

第一行输入一个整数\(T\),表示共有T组测试数据\((0 < T < 100)\)
每一组数据都是先输入该地图的行数\(m\)与列数\(n(0 < m,n < 100)\)
以下\(m*n\)的矩阵为地图

Output

输出该地图中水池的个数
要注意,每个水池的旁边(上下左右四个位置)如果还是水池的话的话,它们可以看做是同一个水池。



Sample Input

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



Sample Output

2
3



PZ's Solution

1.BFS模板题,1代表时一片水池,0代表非水池;

2.直接扫描一遍地图,有水池时,进行BFS将水池进行标记,累加答案,直到扫描完毕;

  • TAG:BFS广度优先搜索



PZ.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int T,m,n,ans,mp[105][105];
bool vis[105][105];
int fx[]={0,0,1,-1};
int fy[]={1,-1,0,0};
queue<int>qx,qy;
void bfs(int sx,int sy){
	qx.push(sx); qy.push(sy); vis[sx][sy]=1;
	while(!qx.empty()){
		int x=qx.front(),y=qy.front();
		qx.pop(); qy.pop();
		for(int i=0;i<4;++i){
			int nx=x+fx[i],ny=y+fy[i];
			if(mp[nx][ny]==1&&!vis[nx][ny]){
				qx.push(nx); qy.push(ny); vis[nx][ny]=1;
			}
		}
	}
}
int main(){
	scanf("%d",&T);
	while(T--){
		ans=0;
		memset(vis,0,sizeof(vis));
		scanf("%d %d",&m,&n);
		for(int i=1;i<=m;++i)
			for(int j=1;j<=n;++j)
				scanf("%d",&mp[i][j]);
		for(int i=1;i<=m;++i)
			for(int j=1;j<=n;++j)
				if(mp[i][j]==1&&!vis[i][j]){
					++ans;
					bfs(i,j);
				}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2021-02-03 17:25  PotremZ  阅读(131)  评论(0编辑  收藏  举报