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)−R∣≤D
即:
R
−
D
≤
√
(
x
2
+
y
2
)
≤
R
+
D
R-D≤√(x^2+y^2 )≤R+D
R−D≤√(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)2−y2)⌋+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 )⌉
⌈√((R−D)2−y2)⌉
勾股定理向上取整
由圆对称性 总数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;
}