您的位置:首页 > 其它

SDUT ACM 2013级选拔赛(部分题目)

2014-12-06 21:56 429 查看
真是没sei了,各种不在状态,又困又累,脑袋就和要炸了一样,也不知道怎么了。四个小时真是一点没浪费,真的算是重新审视了一下自己。这一阵一直乱七八糟的搞来搞去,也没点目的性,算是一直在看算法,算法也没说有多少精进,数学类型靠思维的真的感觉有点无力,反应真的很慢,感觉做题还是太少了,涉猎的面太窄,既然知道了,接下来就去做吧,时间略紧。下面进入正题:

迷之博弈

题目描述

FF喜欢博弈,今天又开始了一场博弈。
将n个棋子摆成一条直线,编号为1到n。两个人轮流取棋子,每回合取一次且只能按照下述两种方法的一种取。
1,任取一个棋子。
2,任取两个棋子且这两个棋子的编号是连续的。
FF为了彰显高手风范总是让对方先手。现在假设两个人都足够聪明,对于给出的n,FF是否能赢。取得最后一个棋子的选手获得胜利。

输入

多组输入,每组一个正整数n(1<= n <= 300)。

输出

若FF能胜则输出“Yeah!”,否则输出“Why
are you so ben?”。

示例输入

1
2


示例输出

Why are you so ben?
Why are you so ben?


这道题我真是不知道怎么说,一开始直接没画粗来,后来想着原先做过一个圆桌铺硬币,好像是先弄的那个人赢,所以我在想是不是这道题也是这样,然后。。。你懂得,A了。若是某位大牛此时再看,你恰好会,请留言,不胜感激。

#include <stdio.h>
int main()
{
int n;
while(~scanf("%d",&n))
{
printf("Why are you so ben?\n");
}
return 0;
}


迷之好奇

题目描述

FF得到了一个有n个数字的集合。不要问我为什么,有钱,任性。
FF很好奇的想知道,对于数字x,集合中有多少个数字可以在x前面添加任意数字得到。
如,x = 123,则在x前面添加数字可以得到4123,5123等。

输入

多组输入。
对于每组数据
首先输入n(1<= n <= 100000)。
接下来n行。每行一个数字y(1 <= y <= 100000)代表集合中的元素。
接下来一行输入m(1 <= m <= 100000),代表有m次询问。
接下来的m行。
每行一个正整数x(1 <= x <= 100000)。

输出

对于每组数据,输出一个数字代表答案。

示例输入

3
12345
66666
12356
3
45
12345
356


示例输出

1
0
1


看到n,m的取值100000是不是吓哭了?我也是这么吓哭的,而且我能说我盯着看了好长时间才看懂这道题么?
思路:用哈希做,储存每一个数值y的后面位数(例如12345,,你可以把它们分解成5,45,345,2345然后把它们当做数组的下标,然后哈希表存储的是该数字的下标有几个,12345就没必要了因为前面不能加,也不可能是它) 另外用哈希做一定要注意这个地方有一个坑!真是坑哭了,例如10086 当你%100,%1000,%10000的时候都是86,他会把这个当成三次,实际上才一次。所以一定要避开

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int a[100010];
int hash[100010];
int main()
{
int n,m,x;
int i,j,t;
int flag;
int cnt;
int site,site1;

while(~scanf("%d",&n))
{
memset(hash,0,sizeof(hash));
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
site=a[i]%10;
cnt=10;
site1=100;
for(;;)
{
if(site==a[i])
{
break;
}
else
{
if(site1!=site)//这个地方,大坑!
{
hash[site]++;
site1=site;
}
cnt*=10;
site=a[i]%cnt;
}
}
}
scanf("%d",&m);
for(i=0; i<m; i++)
{
scanf("%d",&x);
printf("%d\n",hash[x]);
}
}
return 0;
}


迷之节约

题目描述

FF超级有钱,最近又买了n个(1 <= n <= 300)小岛,为了能在岛之间游玩,FF决定要在岛之间修桥以保证任意两岛之间都要可达。但是FF又超级抠门,想让造桥费用最小。现在由于技术原因,一座桥的造价为两桥之间直线距离的平方。现在给你桥的坐标,让你求最小造价是多少。

输入

多组输入。

对于每组数据,第一行输入n,接下来的n行,每行两个整数x,y(-1000 <= x,y <= 1000)代表桥的坐标。

输出

对于每组数据输出一个整数代表最小花费。

示例输入

2
1 1
1 2


示例输出

1


打眼一看这是一道最小生成树的问题,和其余那些裸地差不多,只不过这道题需要你自己计算权值,而且是每个的标号都是每一行的行的行值。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define inf 99999999
int map[310][310];
int dis[310];
int vis[310];
int sum;
struct node
{
int x,y;
}q[1010];
void prim(int n)
{
int i,j,k;
int min;
sum=0;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
dis[i]=map[1][i];
dis[1]=0;
vis[1]=1;
for(i=2;i<=n;i++)
{
min=inf;
for(j=1;j<=n;j++)
{
if(dis[j]<min&&!vis[j])
{
min=dis[j];
k=j;
}
}
if(min==inf)
break;
vis[k]=1;
sum+=min;
for(j=1;j<=n;j++)
{
if(dis[j]>map[j][k]&&!vis[j])
{
dis[j] = map[j][k];
}
}
}
printf("%d\n",sum);
}

int main()
{
int n,m;
int i,j;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
map[i][j]=0;
else
map[i][j]=inf;
}
}
for(i=1;i<=n;i++)
{
scanf("%d %d",&q[i].x,&q[i].y);
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j)
{
m=((q[i].x-q[j].x)*(q[i].x-q[j].x) + (q[i].y-q[j].y)*(q[i].y-q[j].y));
map[i][j]=map[j][i]=m;
}

prim(n);
}
return 0;
}


迷之期望

题目描述

FF一直有一个梦想,就是把CF打到紫名。可是现在有一个问题,FF并不是每场都能涨分。我们现在将这个问题简化,假设现在FF的分数为x,每一场增加a分的概率为p,增加0分的概率为1-p,现在请你计算一下FF突破1700的期望场数是多少。

输入

每组输入x(0 <= x <= 1700),a (0 <= a <= 100),p (0 <= p <= 1),x,a为整数,p为浮点数。

输出

每组输出输出一行。若能突破1700,则输出一个浮点数代表答案,保留小数点后三位。
否则输出 Why are you so ben? 。

示例输入

1700 1 1
1699 100 1
0 0 0


示例输出

0.000
1.000
Why are you so ben?


这道题问的是突破1700分所需要的场次的期望,主要看的是当前分数和1700分的差值。其实在这个题里有几个比较特殊的地方,当你的分数是1700分的时候就是0场,当你的分数比1700分小的时候即差值大于0,如果此时你的加分或者加分的概率是0的话你就一直是笨蛋(这个可能有人忘了)。再说说期望的场次这么个玩意,你要怎么求,如果你的差值取余一场增加的分数的值==0,那么所得结果除以当前的加分概率即可,一开始写的是乘以数据都对,可是忽略了小数。(假设你的差值是4,你的一场加分是2,概率是0.5你怎么求,如果当前的加分概率是1的话你只需要两场就够了,也就是4/2/1,所以换成0.5的话自然是4/2/0.5了)
否则的话要+1,。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int main()
{
int x,a,b;
int n;
double p;
double cnt;
double qw;
while(~scanf("%d %d %lf",&x,&a,&p))
{
if(x==1700)
printf("0.000\n");
else if(x>=0&&x<1700)
{
if(a==0||p==0)
printf("Why are you so ben?\n");
else
{
int b=1700-x;
if(b%a!=0)
cnt=b/a+1;
else
cnt=b/a;
qw=cnt/p;
//printf("%d\n",cnt);
printf("%.3lf\n",qw);
}

}

}
return 0;
}


迷之水题

题目描述

FF有一本密码本,每一页上有一个数字x(1 <= x <= 2000000),并且两两不相等。
可以有一天一个小偷偷走了其中一页,FF想知道小偷偷走了那个数字。

输入

只有一组输入。
首先一个数组n <= 2000000,代表密码本的页数。
接下来的一行有n个数,代表完整的密码本。
接下来的一行有n-1个数,代表残缺的密码本。

输出

输出一个整数代表答案。

示例输入

3
1 2 3
3 1


示例输出

2


n的范围是2000000以内,要是开个数组的话一个个的找肯定超时,所以用快排从小到大排序后,然后比对就好。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
int a[2000010];
int b[2000010];
int main()
{
int n,i,j;
int flag=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(j=1;j<=n-1;j++)
scanf("%d",&b[j]);
sort(a+1,a+n+1);
sort(b+1,b+n);
for(i=1;i<=n;i++)
{
if(a[i]!=b[i])
{
printf("%d\n",a[i]);
flag=1;
break;
}
}
if(!flag)
printf("%d\n",a[i-1]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: