第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题

时间限制: 2 Sec   内存限制: 128 MB
提交: 63   解决: 28
[ 提交][ 状态][ 讨论版]

题目描述

我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数、循环节以及循环节长度

输入

输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100

输出

分别输出这个小数的循环节的长度、循环节以及循环次数,中间以一个空格间隔

样例输入

8.6987698769876987
0.666
5.1

样例输出

4 6987 41 6 31 1 1


//这是南阳oj上329的ac代码,懒得改了,就是格式问题
#include<stdio.h>
#include<string.h>
char str[300];
char s[300];
int next[300];
int len;
void Get_Next()
{
	int i=0,j=-1;
	next[0]=-1;
	while(i<len)
	{
		if(j==-1 || s[i]==s[j])
		{
			++i,++j;
			next[i]=j;
		}
		else
			j=next[j];
	}
}
int main()
{
	int i,T;
	scanf("%d",&T);
	while(T--)	
	{
		scanf("%s",str);
		len=strlen(str);
		for(i=0;i<len;++i)
		{
			if(str[i]=='.')
				break;			
		}
		int k=0;
		for(i=i+1;i<len;++i)
			s[k++]=str[i];
		len=k;
		Get_Next();
		printf("%d ",len-next[len]);//最大字符串长度 
		for(i=0;i<len-next[len];++i)
			printf("%c",s[i]);
		printf(" ");
		
		printf("%d\n",len/(len-next[len]));//重复几次 
	}
	return 0;
}



问题 B: MZY寻宝

时间限制: 1 Sec   内存限制: 128 MB
提交: 163   解决: 50
[ 提交][ 状态][ 讨论版]

题目描述

贪心的MZY去一个迷宫寻宝。已知:若MZY在位置(x, y),他下一次只能移动到(x-1, y)、(x+1, y)、(x, y-1)、(x, y+1)四个位置中的任一个(前提不能越界)。
毕竟他不是我,我可以直接飞到宝物那里去。由于MZY比较笨拙,他移动一步需要1分钟。请你帮他算出找到宝物所需要花费的最少时间。

迷宫是一个N*M的地图,图中只有四个数字。
0:此处是空的,可以走
1:此处有障碍,不可以走
2:MZY起点
3:宝物位置(只有一个宝物)

题目保证CZY至少有一条路可以到达宝物位置。

输入

输入数据有多组。

每组以两个整数N和M开始,分别表示迷宫的行数和列数,接下来N行每行有M个数。(1 <= N, M <= 10)

输出

输出MZY找到宝物的最少需要花费的时间。(以秒为单位)

样例输入

2 2
0 2
1 3

样例输出

60


//BFS
#include<cstdio>
#include<queue>
using namespace std;
struct walk
{
	int x,y;
	int time;
	friend bool operator < (walk a,walk b)
	{
		return a.time>b.time;
	}
};
int n,m;
int map[20][20];
int sx,sy,ex,ey;
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
int min_time;
bool judge(int x,int y)
{
	if(x>n ||x<1||y>m||y<1||map[x][y]==1) return 0;
	return 1;
}
void BFS()
{
	walk pos,next;
	priority_queue<walk>q;
	pos.x=sx;
	pos.y=sy;
	pos.time=0;
	map[sx][sy]=1;
	q.push(pos);
	while(!q.empty())
	{
		pos=q.top();
		q.pop();
		for(int i=0;i<4;++i)
		{
			next.x=pos.x+dx[i];
			next.y=pos.y+dy[i];
			next.time=pos.time+1;
			if(judge(next.x,next.y))
			{
				if(next.x==ex&&next.y==ey)
				{
					min_time=next.time;
				}
				map[next.x][next.y]=1;
				q.push(next);
			}
		}		
	}
}
int main()
{
	int i,j;
	while(~scanf("%d%d",&n,&m))
	{
		for(i=1;i<=n;++i)
		{
			for(j=1;j<=m;++j)
			{
				scanf("%d",map[i]+j);
				if(map[i][j]==2)
				{
					sx=i,sy=j;
				}
				if(map[i][j]==3)
				{
					ex=i,ey=j;
				}
			}
		}

		BFS();
		printf("%d\n",min_time*60);
	}
	return 0;
}





问题 C: CZY的组合数烦恼

时间限制: 3 Sec   内存限制: 128 MB
提交: 46   解决: 21
[ 提交][ 状态][ 讨论版]

题目描述

czy最近对组合数产生了浓厚的兴趣,一天他心血来潮,想排n个数字,但是很快他发现种类太多了,于是他决定从中随机找出m个数排,但还是太多了,所以他想请聪明的你写个程序帮助他找到所有种类的排列

输入

输入包括多组测试数据,每组包括一行整数n(1<=n<10),m(1<=m<=n),空格间隔

输出

按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。

样例输入

5 3

样例输出

543
542
541
532
531
521
432
431
421
321

提示



#include<stdio.h>
#include<string.h>
#define INF 0xfffffff
int a[20];
bool vis[20];
int m,n;
void DFS(int cnt)
{
	if(cnt==n+1)
	{
		for(int i=1;i<=n;++i)
		{
			printf("%d",a[i]);
		}
		printf("\n");
		return ;
	}
	for(int i=m;i>=1;--i)
	{
		a[cnt]=i;
		if(vis[i]==0&&a[cnt]<a[cnt-1])
		{
			
			vis[i]=1;
			DFS(cnt+1);
			vis[i]=0;
		}
	}
}
int main()
{
	while(~scanf("%d%d",&m,&n))
	{
		a[0]=INF;
		memset(vis,0,sizeof(vis));
		DFS(1);
	}
	return 0;
}







问题 D: CZY追女孩

时间限制: 1 Sec   内存限制: 128 MB
提交: 91   解决: 13
[ 提交][ 状态][ 讨论版]

题目描述

CZY遇到了一个萌妹子,他使出浑身解数想要博得她的好感,但是妹子居然是个数学学霸!一天,那个女孩在解数列问题时遇到了一点麻烦,她有数列的前3项,数列不是等比数列就是等差数列,她很想知道这个数列的第n项是什么,但是n可能很大,她算不出来,CZY很想帮她,可是CZY是个学渣,于是想请聪明的你来帮忙求出数列的第n项,由于数据可能太大了,最后的结果对200907取余就好

输入

输入包含多组测试数据,每组测试数据包含4个整数,前三个整数是数列的前三项,最后一个数是n,四个数的范围都是1~10^9

输出

输出这个数列的第n项%200907

样例输入

1 2 3 5
1 2 4 5

样例输出

516

提示



#include<stdio.h>
#include<math.h>
#define LL long long
#define mod 200907
int res;
LL quick(int a,int b)//快速幂
{
	int ans=res;
	while(b!=0)
	{
		if(b&1) ans=(ans%mod*a)%mod;
		a=(a%mod*a)%mod;
		b>>=1; //b/=2;
	}
	return ans;
}
int main()
{
	int n,i;
	int t1,t2,t3;
	long long res;
	while(~scanf("%d %d %d %d",&t1,&t2,&t3,&n))
	{		
		if(t2-t1==t3-t2)
		{
			res=(t1%200907+(n-1)*(t2-t1))%200907;	//同模定理		
		}
		else
		{
			int q=t2/t1;
			res=t1;
			quick(q,n-1);
			for(i=1;i<n;++i)
			{
				res*=q;
				if(res>200907) res%=200907;
			}		
		}
		printf("%lld\n",res);
	}
	return 0;
}



问题 E: 陈公公找女友

时间限制: 1 Sec   内存限制: 128 MB
提交: 55   解决: 20
[ 提交][ 状态][ 讨论版]

题目描述

话说CZY来到了HPU之后,每天对着电脑码代码,码了一学期了,陈公公有一天敲代码敲累了,此刻的陈公公是身心疲惫啊,他突然想:要是有一个Girlfriend多好?于是,陈公公想要在学校找一个Girlfriend。话说在男女比7:1的比例之下很难找到意中人,是不是?可惜这难不倒我们“英(jing)姿(li)(feng)(fu)”的陈公公,找女友要先买礼物对吧。对于陈公公这种“壕”,当然要买高端大气上档次的啦!陈公公要斥巨资买条钻石手链,送给他心仪已久的女生(从此,陈公公又多了个外号“钻石陈”)。我们都知道手链五颜六色的很吸引人。陈公公也知道女生喜欢颜色比较多的手链,但是手链又不能毫无规律的颜色多而已。我们要买的手链必须是颜色够多,还要有规律,什么叫做有规律?就是有循环的。假如给定参照手链“RGB,再给一个手链比如“RGBRGBRGB”它包含了3个参照手链。陈公公称包含值为:美丽度。因为包含3个参考串,所以这个手链美丽度就为3.

陈公公想要买一个美丽度大于1的手链,但是又不能只有一种颜色,怎么挑一个最好的呢?这个问题有点难想,并且可惜陈公公对颜色的分辨能力不够高(轻微色盲),不能很好的判断买哪一条手链,要不是陈公公自己都能编程解决这个问题了。陈公公很无奈啊,他想到了有爱心的协会成员,希望求助协会成员,请你帮他选一个最美的手链。这关乎到陈公公能否追到心意的女孩啊!人生大事啊!陈公公说了,能帮他解决这个问题的童鞋,他就会请你吃饭!PS:帮陈公公解决这个问题的人,记得找陈公公请客。

输入

有多组测试数据,输入先给出参考手链(参考手链长度大于1),然后输入一个T(0<T<20),代表陈公公选的T组数据。每组数据第一行是参照手链,第二行是陈公公想知道美丽度的手链(长度不小于参考手链)。由于陈公公比较壕,所以他选的手链的珠子最多可以达到100000。

输出

输出数据也有T行,每行输出,最大美丽度,和相应的手链。如果美丽度相同就输出手链最长的,看下面测试样例。

样例输入

RGB4RGBRGBRGBRGBRGBRGBWRGBWRGBWRGRGBRGGRBGRWW3RWWWWRRWWWWRWRWRWRWWWR5WWRWWWWWRWWRWRWWWWWWWWWRWRWRWRWRRWRWRWWW

样例输出

3 RGBWRGBWRGBW1 RWWWWRW2 WWWRWWRWR

提示



#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char substr[100010];
int next[100010];
int len;
char *q;
int max;
int len1,len2;
struct value
{
	char str[100010];
	int num;
	int len;
}arr[30];
bool cmp(value a,value b)
{
	if(a.num==b.num) return a.len>b.len;
	return a.num>b.num;
}
void Get_Next()
{
	int i=0,j=-1;
	next[0]=-1;
	while(i<len1)
	{
		if(j==-1 || substr[i]==substr[j])
		{
			++i,++j;
			next[i]=j;
		}
		else
			j=next[j];
	}
}
int KMP(int t)
{
	int i=0,j=0;
	int cnt=0;
	while(i<len2)
	{
		if(j==-1 || arr[t].str[i]==substr[j])
		{
			++i,++j;
			if(j==len1)
			{
				cnt++;
				j=0;
			}
		}
		else
			j=next[j];
	}
	return cnt;
}
int main()
{
	int n;
	while(~scanf("%s",substr))
	{
		len1=strlen(substr);
		Get_Next();
		scanf("%d",&n);
		for(int i=0;i<n;++i)
		{
			scanf("%s",arr[i].str);
			len2=strlen(arr[i].str);
			arr[i].len=len2;
			arr[i].num=KMP(i);
			
		}
		sort(arr,arr+n,cmp);
		printf("%d %s\n",arr[0].num,arr[0].str);
	}
	return 0;
}




问题 F: CZY的YY难题

时间限制: 1 Sec   内存限制: 128 MB
提交: 6   解决: 1
[ 提交][ 状态][ 讨论版]

题目描述

CZY终于又和萌妹子的关系又进了一步,终于知道了妹子的名字,原来她叫YY,CZY跟着那个女孩也学到了很多的数学知识,CZY感觉自己快要超神了,于是嘚瑟起来,YY对此不屑一顾,冷笑一声“呵呵”后,便给CZY出了一道数学题,YY给了CZY一个数n,又给了m个数,让他从中找一些数,让这些数的和等于n,并让他把所有的情况写出来。这下可把CZY给打击到了,于是他又来请教聪明的你,请你帮帮他

输入

题目包含多组测试数据,每组测试数据包含两行,第一行包含两个整数n,m(1<=n,m<1000)

第二行包含m个数

输出

按从大到小的顺序输出所有符合的情况,没有符合的情况就输出NONE

样例输入

4 64 3 2 2 1 15 32 1 1400 1250 50 50 50 50 50 25 25 25 25 25 25

样例输出

43+12+22+1+1
NONE
50+50+50+50+50+50+25+25+25+25
50+50+50+50+50+25+25+25+25+25+25

提示



#include<stdio.h>
#include<string.h>
int sum,n;
int a[1010];
int res[1010]={10000};
bool vis[1010];
int j;
bool flag=0;
void DFS(int m,int cnt)
{
	int i;//这个i DFS时要用上,且作用很大,一定得放在里面,我一开始定义了个全局变量,找了快两小时 才找到 
	if(m==0)
	{
		flag=1;
		for(j=1;j<cnt-1;++j)
			printf("%d+",res[j]);
		printf("%d\n",res[j]);
		return ;
	}
	for(i=1;i<=n;++i)
	{
		//
		if(!vis[i]&&m-a[i]>=0&&a[i]<=res[cnt-1])
		{
			vis[i]=1;
			res[cnt]=a[i];                                             
			DFS(m-a[i],cnt+1);
			vis[i]=0;
			while(a[i]==a[i+1]&&i<=n) ++i;
		}
	}

}
int main()
{
	int i;
	while(~scanf("%d%d",&sum,&n),sum+n)
	{
		flag=0;
		for(i=1;i<=n;++i)
		{
			scanf("%d",a+i);
		}
		printf("Sums of %d:\n",sum); 
		memset(vis,0,sizeof(vis));
		DFS(sum,1);
		if(!flag)printf("NONE\n");
	}
	return 0;
}







问题 G: 打败魔王

时间限制: 2 Sec   内存限制: 128 MB
提交: 43   解决: 6
[ 提交][ 状态][ 讨论版]

题目描述

可怜的公主又被魔王抓走了。魔王这次准备在T时刻与公主成亲,不过公主深信智勇的骑士CZY肯定能将她救出。
已知:公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。
CZY一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那CZY就会被撞死。
CZY在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。

输入

输入有多组测试数据。
每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N*M(1 <= N,M <=10)。T如上所意。
接下去的前N*M表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。

输出

如果CZY能够在T时刻能找到公主就输出“YES”,否则输出“NO”。

样例输入

1 4 2
.#.#

*.#P

样例输出

NO

提示





//BFS
#include <cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct help
{
	int x,y,z;
	int time;
};
char map[15][15][15];
bool vis[15][15][15];
int ex,ey,ez;
int dx[]={0,0,-1,1,0,0};
int dy[]={1,-1,0,0,0,0};
int dz[]={0,0,0,0,-1,1};
int n,m,limit;
bool judge(int x,int y,int z)
{
	if(vis[z][x][y] || x>n || x<1 || y>m || y<1 || map[z][x][y]=='*') 	
		return 0;
	return 1;
}
int BFS()
{
	memset(vis,0,sizeof(vis));
	queue<help>q;
	help pos,next;
	pos.x=1;
	pos.y=1;
	pos.z=0;
	pos.time=0;
	vis[0][1][1]==1;
	q.push(pos);
	while(!q.empty())
	{
		pos=q.front();
		q.pop();
		for(int i=0;i<4;++i)
		{
			next.x=pos.x+dx[i];
			next.y=pos.y+dy[i];
			next.z=pos.z;
			next.time=pos.time+1;					
			if(!vis[next.z][next.x][next.y]&&map[next.z][next.x][next.y]=='#')
			{
				if(map[!next.z][next.x][next.y]=='#'||map[next.z][next.x][next.y]=='*')
				{
					vis[next.z][next.x][next.y]=1;
					continue;
				}				
				next.z=!next.z;				
			}				
			if(judge(next.x,next.y,next.z))
			{				
				if(next.x==ex&&next.y==ey&&next.z==ez)
				{
					return next.time;
				}
				vis[next.z][next.x][next.y]=1;
				q.push(next);			
			}
		}
	}
	return -1;
}
int main()
{
	while(~scanf("%d%d%d",&n,&m,&limit))
	{
		getchar();
		for(int i=0;i<=1;++i)
		{
			for(int j=1;j<=n;++j)
			{
				for(int k=1;k<=m;++k)
				{
					scanf("%c",map[i][j]+k);
					if(map[i][j][k]=='P')
						ez=i,ex=j,ey=k;
				}				
				getchar();
			}
			if(!i)
				getchar();
		}
		int min_time=BFS();
		if(min_time==-1||(min_time>limit)) 
			printf("NO\n");
		else printf("YES\n");
	}
	return 0;
}

/*

1 4 3
.#.#

*.#P
YES

5 5 14
S*#*.
.#...
.....
****.
...#.

..*.P
#.*..
***..
...*.
*.#..
YES
*/





问题 H: CZY的工程

时间限制: 1 Sec   内存限制: 128 MB
提交: 73   解决: 38
[ 提交][ 状态][ 讨论版]

题目描述

CZY总是遇到这样或那样的问题,现在他又遇到了一个,CZY接到一个大的工程,想想这是走上人生巅峰的第一步啊,CZY想想就高兴,可是这个工程太大了,他需要很多人的帮助才可以,但是为了方便工作,CZY希望他的团队两人两人之间都是朋友关系,或者间接是朋友关系。毕竟是大油水的工程啊,来了一群小伙伴报名,CYZ想请聪明的你帮忙算一算,他可以招到的最大的人数是多少

输入

输入包含多组测试数据,每组测试数据第一行一个n,表示来报名的小伙伴们的编号1-100,后边接n行,每行两个整数a b,表示编号a和b的小伙伴是朋友关系

输出

输出包括一行,即CZY可以招到的最大的人数是多少

样例输入

4
1 2
3 4
5 6
1 6

样例输出

4

提示


//并查集
#include<stdio.h>
int per[201];
int peo[201];

void init()
{
	for(int i=1;i<=100;++i)
	{
		per[i]=i;
	}
	for(int i=1;i<=100;++i)
		peo[i]=1;
}
int find(int x)
{
	int r=x;

	while(r!=per[r])
	{
		r=per[r];		
	}
	per[x]=r;
	return r;
}
void join(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		per[fx]=fy;
		peo[fy]+=peo[fx];
	}
}
int main()
{
	int n;
	int a,b;
	while(~scanf("%d",&n))
	{
		init();
		while(n--)
		{
			scanf("%d%d",&a,&b);
			join(a,b);
		}
		int max=-100;
		for(int i=1;i<=100;++i)
		{
			if(per[i]==i)
			{
				if(max<peo[i]) max=peo[i];
			}
		}
		printf("%d\n",max);
	}
	return 0;
}




问题 I: CZY找句子

时间限制: 1 Sec   内存限制: 128 MB
提交: 99   解决: 45
[ 提交][ 状态][ 讨论版]

题目描述

YY喜欢读书,而且总是喜欢从书上摘取好的句子或词语,但是抄完之后她变忘了在哪,于是她就请CZY帮她,CZY感觉这我多我可咋找啊!
于是又来麻烦聪明的你,为了方便CZY早已用高端译码机器把句子变成的数字,他想让你告诉他句子在文章中出现的位置。(位置从1开始)

输入

输入包括多组测试数据,每组测试数据包含三行,第一行包含两个整数n(1<=n<=1000000),m(1<=m<=1000),分别代表文章的长度,和所摘取的句子的长度,
第二行包含n个整数表示文章,第三行包括m各整数表示句子

输出

输出所摘取的句子在文章中的位置

样例输入

13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3

样例输出

6

提示



//KMP

#include<stdio.h>
int arr[110],subarr[110];
int next[110];
int i,j;
int m,n;

int KMP()
{
	i=1;j=1;
	while(i<=m)
	{
		if(arr[i]==subarr[j])
		{
			++i,++j;
			if(j==n+1)
			{
				return i-n;
			}
		}
		else
		{
			j=1;
			i=i-j+2;
		}
	}
}
int main()
{
	while(~scanf("%d%d",&m,&n))
	{
		for(i=1;i<=m;++i)
			scanf("%d",arr+i);
		for(i=1;i<=n;++i)
			scanf("%d",subarr+i);
		printf("%d\n",KMP());
	}
	return 0;
}

//5 2
//1 2 3 4 5 
//2 3



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值