Gym101521GHIJKL-----La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2016

La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2016


题目链接:http://codeforces.com/gym/101521

G . Monorail

题意:给定直道数n、弯道数m,判断是否能组成一个闭合环路,

有则输出由"." “|” “-” " r" “J” “7” “L” 表示对应的图形

题解:(1)M、N必须是偶数

​ (2) N=0时,M必须整除4, M不能等于8

​ (3) M除4余2时,疑似有 (N,M): (2,6) (4,10) …的规律

分类解决,m整除4时有类似如下两种情况:直道加在第一行和最后两行

分别以菱形式扩展和在菱形基础上往右下角扩展

m为8时,三行凸字形,有直道加在第一行和第三行中间

当m为除4余2时,尚待解决

#include<bits/stdc++.h>
using namespace std;
int n,m;
int main() {
	scanf("%d%d",&n,&m);
	if(m%2||n%2) return cout<<"impossible",0;
	if(n==0&&(m%4||m==8))  return cout<<"impossible",0;
	if(m==8) {
		cout<<3<<" "<<4+(n-2)/2<<endl; 
		printf(".r");
		for(int i=1; i<=(n-2)/2; i++) printf("-");
		printf("7.");
		printf("\n");
		printf("rJ");
		for(int i=1; i<=(n-2)/2; i++) printf(".");
		printf("L7");
		printf("\n");
		printf("L-");
		for(int i=1; i<=(n-2)/2; i++) printf("-");
		printf("-J");
		return 0;
	}
	if(m%4==0) {
		cout<<m/4+1<<" "<<m/4+1+n/2<<endl;
		int lp=floor((m/4-1)/2);
		int rp=floor(m/8);
		for(int i=1; i<=lp; i++) printf(".");
		printf("r");
		for(int i=1; i<=n/2; i++) printf("-");
		printf("7");
		for(int i=1; i<=rp; i++) printf(".");
		printf("\n");
		for(int i=1; i<=floor((m/4-1)/2); i++) {
			lp--;
			rp--;
			for(int i=1; i<=lp; i++) {
				printf(".");
			}
			printf("rJ");
			for(int i=1; i<floor((m/4-1)/2)-lp; i++) printf(".");
			for(int i=1; i<=n/2; i++) printf(".");
			for(int i=1; i<floor(m/8)-rp; i++) printf(".");
			printf("L7");
			for(int i=1; i<=rp; i++) {
				printf(".");
			}
			printf("\n");
		}
		if((m/4)%2==1) {
			for(int i=1; i<=floor((m/4-1)/2); i++) {
				for(int i=1; i<=lp; i++) printf(".");
				printf("L7");
				for(int i=1; i<floor((m/4-1)/2)-lp; i++) printf(".");
				for(int i=1; i<=n/2; i++) printf(".");
				for(int i=1; i<floor(m/8)-rp; i++) printf(".");
				printf("rJ");
				for(int i=1; i<=rp; i++) 	printf(".");
				printf("\n");
				lp++;
				rp++;
			}
			for(int i=1; i<=lp; i++) printf(".");
			printf("L");
			for(int i=1; i<=n/2; i++) printf("-");
			printf("J");
			for(int i=1; i<=rp; i++) printf(".");
		} else {
			rp--;
			printf("L7");
			for(int i=1; i<floor((m/4-1)/2)-lp; i++) printf(".");
			for(int i=1; i<=n/2; i++) printf(".");
			for(int i=1; i<floor(m/8)-rp; i++) printf(".");
			printf("L7");
			printf("\n");
			lp++;
			for(int i=1; i<floor((m/4-1)/2); i++) {
				for(int i=1; i<=lp; i++) printf(".");
				printf("L7");
				for(int i=1; i<floor((m/4-1)/2)-lp; i++) printf(".");
				for(int i=1; i<=n/2; i++) printf(".");
				for(int i=1; i<floor(m/8)-rp; i++) printf(".");
				printf("rJ");
				for(int i=1; i<=rp; i++) printf(".");
				printf("\n");
				lp++;
				rp++;
			}
			for(int i=1; i<=lp; i++) printf(".");
			printf("L");
			for(int i=1; i<=n/2; i++) printf("-");
			printf("7");
			for(int i=1; i<floor((m/4-1)/2)-lp; i++) printf(".");
			for(int i=1; i<floor(m/8)-rp-1; i++) printf(".");
			printf("rJ");
			for(int i=1; i<=rp; i++) printf(".");
			printf("\n");
			lp++;
			rp++;
			for(int i=1; i<=lp; i++) printf(".");
			for(int i=1; i<=n/2; i++) printf(".");
			printf("LJ");
			for(int i=1; i<=rp; i++) printf(".");
		}
		return 0;
	}
    cout<<"impossible";
    return 0;
}

H. Pokemon GO

题意:一幅无向带权图,给出点的个数和边以及边的长度,问是否存在一条路径使得从点A到点B路程恰好为K(可重复),如果有打印路径,没有则打印Impossible。

题解:使用邻接表创建无向带权图G,dfs(图(G),目前位置(i),目前总路程(len))查找路径。最开始为dfs(G,A,0),目标是dfs(G,B,K)。

#include<bits/stdc++.h>
using namespace std;
int N,M,K,A,B,way[5000],cnt=0;
#define  MAX_VERTEX_NUM 1005//最大顶点个数
typedef struct ArcNode{
    int adjvex;//邻接点在数组中的位置下标
    struct ArcNode * nextarc;//指向下一个邻接点的指针
    int length;
}ArcNode;
typedef struct VNode{
    int data;//顶点的数据域
    ArcNode * firstarc;//指向邻接点的指针
}VNode,AdjList[MAX_VERTEX_NUM];//存储各链表头结点的数组
typedef struct {
    AdjList vertices;//图中顶点的数组
    int vexnum,arcnum;//记录图中顶点数和边或弧数
}ALGraph;
void creat(ALGraph &G){
	int i,j,k,length;
	ArcNode *p;
	G.vexnum=N;
	G.arcnum=M;
	for(i=0;i<G.vexnum;i++){//头插法
		G.vertices[i].data=i+1;
		G.vertices[i].firstarc=NULL;
	}
	for(k=0;k<G.arcnum;k++){
		cin>>i>>j>>length;
		p=new ArcNode;
		p->length=length;
		p->adjvex=j;
		p->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p; 
	}
}

void dfs(ALGraph G,int i,int len){//方法没能实现。。。
	ArcNode *p;
	int k;
	p=NULL;
	cout<<"case:  "<<i<<"   "<<len<<endl;
	if(i==B&&len==K){
		cout<<"YES"; 
	}
	else{
		for(p=G.vertices[i].firstarc;p;p=p->nextarc){
			if(p->length+len<=K){
				int len1=len;
				len1+=p->length;
				k=p->adjvex;
//				cout<<k<<endl;
				dfs(G,k,len1); 
			}else continue;
		}
	}
} 
//问题1:无向图没有体现无向性,没能重复走。
//问题2:即使确定了有该路径,但是没能保存路径的顺序。
int main(){
	ALGraph G;
	cin>>N>>M>>K;
	cin>>A>>B;
	creat(G);
	dfs(G,A,0);
    return 0;
} 

I. RNG

题意:给定一串15位序列{Xn}(部分缺失且X1必缺),求该序列符合下述递推规则的a,b,c,d,m,X1,其中 Xi∈{1,2,3,4},没有符合的输出6个-1
X ( i + 1 ) = ( a X i 3 + b X i 2 + c X i + d ) m o d ( m ) X_(i+1)=(aX_i^3+bX_i^2+cX_i+d)mod(m) X(i+1)=(aXi3+bXi2+cXi+d)mod(m)
题解:如果已知给定序列存在满足的解,则m=5时必有解,枚举0<=a,b,c,d<=4, m=5, 1<=x<=4,

共5 * 5 * 5 * 5 * 4=2500种, 满足递推规则输出

#include<bits/stdc++.h>
using namespace std;
int a,b,c,d,m=5,x1,f[15];
bool flag;
string s;
int main() {
	cin>>s;
	for(int x1=1; x1<=4; x1++) {
		f[0]=x1;
		for(int a=0; a<=4; a++) {
			for(int b=0; b<=4; b++) {
				for(int c=0; c<=4; c++) {
					for(int d=0; d<=4; d++) {
						flag=false;
						for(int i=1; i<=14; i++) {
							f[i]=(a*f[i-1]*f[i-1]*f[i-1]+b*f[i-1]*f[i-1]+c*f[i-1]+d)%m;
							if(s[i]!='?') {
								if(f[i]!=s[i]-'0') {
									flag=false;
									break;
								} else {
									flag=true;
								}
							}
						}
						if(flag) {
//							for(int i=0;i<=14;i++){
//								cout<<f[i];
//							}
//							cout<<endl;
							return cout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<m<<" "<<x1<<endl,0;
						}
					}
				}
			}
		}
	}
	printf("-1 -1 -1 -1 -1 -1");
}

J. Posters

题意:两人在公告栏(h ,w)上贴海报(ha ,wa),(hb ,wb); 第一个人先贴(ha ,wa)

Plan A: 让第二个人也能贴上去;能满足Yes,不能满足No ;

Plan B: 让第二个人贴不上去:能满足Yes,不能满足No;

第一个人如果贴不上去输出No:(ha>h || wa>h)

题解

1、对于Plan A:两种情况满足任意一种就Yes

2、对于Plan B: 放中间。两种情况下,第二张可以贴上去

当以上两种情况都不满足Yes,否则No;

注意:当第一张海报尺寸超出公告栏尺寸时也为No;(即ha>h || wa>w)

#include<bits/stdc++.h>
using namespace std;
int h,w,ha,hb,wa,wb;
int main() {
	cin>>h>>w>>ha>>wa>>hb>>wb;
	if((ha<=h&&hb<=h&&(wa+wb)<=w)||(wa<=w&&wb<=w&&(ha+hb)<=h)) {
		cout<<"Yes"<<endl;
	} else {
		cout<<"No"<<endl;
	}
	if(ha>h||wa>w) {
		cout<<"No"<<endl;
	} else {
		bool flag=false;
		if(hb<=(h-ha)/2.0&&wb<=w) {
			flag=true;
		}
		if(wb<=(w-wa)/2.0&&hb<=h) {
			flag=true;
		}
		if(flag) {
			cout<<"No"<<endl;
		} else {
			cout<<"Yes"<<endl;
		}
	}
	return 0;
}

K. Lattice Points

题意:求与以R为半径的圆(0,0),所有距离小于D的整数坐标点个数,令该点(x,y)

题解

由题意得:
∣ √ ( x 2 + y 2 ) − R ∣ ≤ D |√(x^2+y^2 )-R|≤D (x2+y2)RD
即:
R − D ≤ √ ( x 2 + y 2 ) ≤ R + D R-D≤√(x^2+y^2 )≤R+D RD(x2+y2)R+D
(1)当R<=D时,求以R+D为半径的大圆内(含边界)的整数坐标点的个数

​ 令第一象限符合要求的个数为cnt1;

​ 求cnt1: y从1到R+D,每行点个数累加求和

​ 每行的点的个数为:
⌊ √ ( ( R + D ) 2 − y 2 ) ⌋ + 1 ⌊√((R+D)^2-y^2 )⌋+1 ((R+D)2y2)+1
​ 勾股定理向下取整+y轴上的点

​ 由圆的对称性,总的个数为: 4*cnt1+1;(原点)

(2)当R>D时, 求以R+D为半径的圆与以R-D为半径的圆中间的圆环有多少个整数点(两条边界包括)

​ 即: 求大圆内的点(包含边界)— 小圆内的点(不包含边界)

​ 大圆内的点(含边界)参考(1) :总数为4*cnt1+1;

​ 小圆内的点(不含边界):令第一象限符合要求的个数为cnt2;

​ 求cnt2: y从1到R-D,每行点个数累加求和

​ 每行点个数为:
⌈ √ ( ( R − D ) 2 − y 2 ) ⌉ ⌈√((R-D)^2-y^2 )⌉ ((RD)2y2)
​ 勾股定理向上取整

​ 由圆对称性 总数4*cnt2+1;

即:Answer=4*(cnt1-cnt2);

#include<bits/stdc++.h>
using namespace std;
typedef  unsigned long long ll;
ll r,d,cnt1=0,cnt2=0,cnt3=0;
int main(){
	cin>>r>>d;
	for(ll i=1;i<=r+d;i++){//求大圆内(含边界)的整数坐标点个数
		cnt1+=floor(sqrt((r+d)*(r+d)-i*i))+1;		
	}	
	if(r<=d) return cout<<4*cnt1+1,0;
	for(ll i=1;i<=r-d;i++){//求小圆内(不含边界)的整数坐标点个数
		cnt2+=ceil(sqrt((r-d)*(r-d)-i*i));
	}
	cout<<4*(cnt1-cnt2);
	return 0; 
}

L. Textbook Game

题意:

​ 给出页数和每页的人脸数,两人PK翻一页,人脸数多获胜;求当第一个人翻第i页时,其胜、平、负的几率各为多少。

题解:计算几页比他翻的多和少即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,big,small,eq;
int f[maxn];
vector<int>up;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&f[i]);
		up.push_back(f[i]);
	}
	sort(up.begin(),up.end());
	for(int i=1;i<=n;i++){
	 big=0;
	 small=0;
	 eq=0;
	 int t1,t2;
	 t1=lower_bound(up.begin(),up.end(),f[i])-up.begin();  //找有几页更少
	 small=t1;
	 if(up[n-1]==f[i])   big=0;
	 else {
			t2=upper_bound(up.begin(),up.end(),f[i])-up.begin(); //找几页更多
		    big=n-t2;
	 }
	 eq=n-big-small;
	 printf("%.6f %.6f %.6f\n",(float)(big)/n,(float)(eq)/n,(float)(small)/n);
	}	
	return 0; 
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值