Case Time Limit:1000MS
Time Limit: 3000MS | Memory Limit: 65536K | |||
Total Submissions: 28 | Accepted: 17 |
Description
大家都知道,现在使用键盘的是下列字母:
qwertyuiop
asdfghjkl;
zxcvbnm,./
BSNY在联系盲打,但是有时候,他盲打会偏移一个,或者左偏或者右偏,如果左偏,比如BSNY想打f,实际按了d;反之,如果右偏,想打d,实际打了f。
为了方便,我们用L,R表示左偏和右偏。
给你BSNY打出来的字母,问BSNY原本想打的字母是什么?
Input
先输入L或R
然后一行字符
Output
输出BSNY原本想打的字符
Sample Input
R s;;upimrrfod;pbr
Sample Output
allyouneedislove
Hint
保证打的字符在上述键盘框内, 字符串长度小于10000
这是一道水题,就是模拟,但是读题要仔细啊,它给出的字符串是现在的,然后L,R代表的是他经过了什么变化而输出现在的字串的,然后叫你输出原来的字符串。
我的方法是分情况讨论,L,R,然后每次for一遍所有的键盘,然后再输出。
但是有更好的方法:(直接上代码)
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
int main(){
string s = "qwertyuiopasdfghjkl;zxcvbnm,./";
char d;
cin >> d;
string p;
cin >> p;
for (int i = 0; i < p.size(); i++) {
int ch = s.find(p[i]);
if (d=='L') cout << s[ch+1];
else cout << s[ch-1];
}
cout<<endl;
return 0;
}
它的思想就是把所有的都存进去,然后再在里面判断是L还是R,然后输出+1操作还是-1操作。
Case Time Limit:1000MS
Time Limit: 3000MS | Memory Limit: 65536K | |||
Total Submissions: 27 | Accepted: 14 |
Description
对于一个正整数n,我们可以定义一个函数:
f(n) = -1 + 2 - 3 + .. + ( - 1)nn
现在给你一个n,希望你可以算出f(n)
#include<stdio.h>
#include<string.h>
typedef __int64 ll;
ll f;
int main(){
ll n;
int i,j,k;
scanf("%I64d",&n);
f=0;
if(n%2) f=(n/2+1)*(-1);
else f=n/2;
printf("%I64d\n",f);
}
Case Time Limit:1000MS
Time Limit: 3000MS | Memory Limit: 65536K | |||
Total Submissions: 91 | Accepted: 18 |
Description
有N条线段,已知每条线段的起点和终点(1~500000内的整数),然后有M个询问,每次询问一个点(1~500000内的整数),求这个点在多少条线段上出现过?
Input
第一行N线段条数
接下来N行,每行两个数,线段的起点和终点
第N+2行一个数M询问个数
接下来M行,每行一个点
Output
对于每个询问,求答案
#include<stdio.h>
#include<string.h>
__int64 a[555555];
int main(){
int n,i,j,k,m;
scanf("%d",&n);
memset(a,0,sizeof(a));
int s,t;
for(i=1;i<=n;i++){
scanf("%d%d",&s,&t);
a[s]++;
a[t+1]--;
}
for(i=1;i<=500001;i++) a[i]+=a[i-1];
scanf("%d",&m);
__int64 sum=0;
while(m--){
sum=0;
scanf("%d",&k);
sum=a[k];
printf("%I64d\n",sum);
}
}
Case Time Limit:1000MS
Time Limit: 6000MS | Memory Limit: 65536K | |||
Total Submissions: 34 | Accepted: 11 |
Description
有n个小朋友,编号1到n,老师将他们分成两队,但分完后小朋友又乱跑了,不知道谁分在哪队,于是他求助很多小机器人,编号1到m,这些机器人会按顺序提示一些信息。
提示的信息是这样的: a b, 表示小朋友a和小朋友b不在同一队。
但是这些机器人偶尔会撒谎,老师就来请求你帮忙,看看哪个机器人最先撒谎。撒谎的规则是这样的,只要当前机器人说的信息与之前所有信息不冲突,就不算撒谎,如果冲突了,就算撒谎了。
Input
输入n,m
然后输入m行,第i行为机器人i提供的信息
Output
如果没机器人撒谎,输出”OK”
否则输出第一个撒谎机器人的编号
Sample Input
3 3 1 2 2 3 1 3
Sample Output
3
Hint
前两个机器人说的没冲突,得出1和3应该在同一队,所以第三个机器人撒谎了
1<=n<=5000 1<=m<=100000
#include<stdio.h>
#include<string.h>
int f[5555*2],n,m;
#define maxn 111110
int x[maxn],y[maxn];
#define MAXN 2*n
void init(){
for(int i=1;i<=MAXN;i++)
f[i]=i;
}
int getf(int v){
if(f[v]==v)
return v;
else {
f[v]=getf(f[v]);
return f[v];
}
}
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
init();
for(i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]);
int flag=1;
for(i=1;i<=m;i++){
int xx=getf(x[i]);
int yy=getf(y[i]);
//如果两个人的祖先相同,那么肯定是不成立的;
if(xx==yy){
flag=0;
printf("%d\n",i);
break;
}
else{
f[xx]=getf(y[i]+n);
f[yy]=getf(x[i]+n);
}
}
if(flag) printf("OK\n");
}
其原理就是类似于不停的把它们合并;
注意这里xx合并到y[i]+n,因为它肯定是和它们不在同一个集合内的。
而yy合并到x[i]+n.同理。
Case Time Limit:1000MS
Time Limit: 3000MS | Memory Limit: 65536K | |||
Total Submissions: 29 | Accepted: 11 |
Description
BSNY在练打枪,他固定站在一个位置,不远处有个点会朝着某个方向释放飞盘,现在BSNY想知道,他能否击中这个飞盘。
为了使得问题简单,我们可以将射击场看成一个平面。BSNY所站的位置视为点(x1, y1), 发射飞盘的位置也视为点(x0, y0)。飞盘飞行的速度和方向我们用速度向量表示(dx, dy)。飞盘视为圆,刚开始圆心落在发射点,半径为r0, 子弹也视为圆,刚开始圆心落在BSNY站的点,半径为r1, 子弹的速度为v,方向可以任意方向发射。
问,BSNY发射的子弹能否打到飞盘(边缘接触到就算打中)。
能打中,输出最少花费的时间(保留4位小数); 不能打中,输出”Impossible”
Input
输入T,表示有T组测试数据
对于每组测试数据,第一行输入x0, y0
第二行输入x1, y1
第三行输入dx, dy
第四行输入r0, r1
第五行输入v
Output
能打中,输出最少花费的时间(保留4位小数); 不能打中,输出”Impossible”
Sample Input
2 0.0 0.0 4.0 0.0 1.0 0.0 1.0 1.0 2.0 0.0 0.0 300.0 400.0 -3.0 -4.0 1.0 1.0 5.0
Sample Output
0.6667 Impossible
Hint
T<=100 其余参数可能为小数,绝对值不超过10000
这里附上题解:
比较难的几何题。几何模型是两个圆,一个跑一个追,我们称跑的那个圆为跑圆,追的那个圆为追圆。跑圆的速度大小和方向是确定的,但追圆的速度大小定了,方向没定。我们很容易想到的就是把跑圆的半径反加到追圆上面,设反加后追圆的半径为R,这样就变成了追圆和跑点的问题。但是后面怎么办就不大好想了。考虑追圆的圆心,如果它的速度大小是v, t时间后,它的圆心轨迹实际上是半径为vt的圆(圆心可覆盖的所有位置就是这个圆的全部)。那么t时间追圆能覆盖的全部位置实际上是(vt+R)的圆的全部。(全部是指包含边界和内部),那么实际上可以看作追圆圆心不变,它的半径不断加大,问何时能碰上跑点。于是问题就简单了,t时刻后跑点的位置是可以表示的,列出它到追圆圆心距离的平方的式子,让其<=R*R,化简后这是是一个2次不等式。at^2+bt+c<=0,后面就是分类讨论了,注意a==0时,退化成一次。否则的话就是抛物线了,用2次方程根与系数的关系等,可以算出结果。数据比较厚道,eps设置为1e-10,1e-9,1e-8,1e-7,1e-6应该都能过的。
腾讯那道就更简单了,直接列方程,将未知数将到只有T,然后解方程就行
其实就是把飞盘的半径附到子弹上去,然后把子弹当成一个园,求它能覆盖到的最大面积就好了。
#include<stdio.h>
#include<string.h>
#include<math.h>
#define eps 1e-9
#define sr(x) (x*x)
int main(){
double x0,y0,x1,y1,dx,dy,r0,r1,v;
int T,i,j,k;
scanf("%d",&T);
while(T--){
scanf("%lf%lf",&x0,&y0);
scanf("%lf%lf",&x1,&y1);
scanf("%lf%lf",&dx,&dy);
scanf("%lf%lf",&r0,&r1);
scanf("%lf",&v);
double a,b,c;
a=sr(dx)+sr(dy)-sr(v);
b=2*x0*dx+2*y0*dy-2*x1*dx-2*y1*dy-2*(r1+r0)*v;
c=sr(x0)+sr(y0)-2*x0*x1-2*y0*y1+sr(x1)+sr(y1)-sr((r0+r1));
//1:当系数a为0时;
if(fabs(a)<=eps){
double time=0;
time=-c/b;
if(time<=eps) puts("Impossible");
else printf("%.4lf\n",time);
}
else {
//求出根来,若不存在,则说明是不可能的;
double data=(double)(b*b-4.0*a*c);
if(data<=eps) puts("Impossible");
else{
//xx代表的是第一个求出来的根,yy是第二个;
double xx,yy;
xx=(-b+sqrt(data*1.0))/(2.0*a);
yy=(-b-sqrt(data*1.0))/(2.0*a);
if((xx<=eps)&&(yy>=eps)) printf("%.4lf\n",yy);
else if(xx>=eps&&yy>=eps){
if(xx-yy>=eps) printf("%.4lf\n",yy);
else printf("%.4lf\n",xx);
}
else if(xx<=eps&&yy<=eps) puts("Impossible");
}
}
}
}
总之,还是不错的,继续加油吧,hades!