NCST 2018-2019秋季学期17级个人排位赛(二)
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,可列出方程:
可得\(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;
}