您的位置:首页 > 编程语言

CodingTrip - 携程编程大赛 (预赛第一场)

2014-04-11 19:54 417 查看


聪明的猴子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1123    Accepted Submission(s): 294


Problem Description

森林中有一排香蕉树(无限长),一只猴子站在其中一棵树上,猴子在跳跃前要先抽取一张卡片,卡片上写有A+1个自然数,其中最后一个是B,前A个数只能小于等于B,卡片上的数字可以相同。猴子每次跳跃先从卡片上任选一个自然数C,然后向左、或向右跳C棵树。猴子的任务是:跳到与它左边相邻的香蕉树上时,就可以吃掉上面的香蕉。

例如,当A=2,B=4时,对于卡片(2, 3, 4),猴子就可以吃到香蕉:它可以先向左跳3棵树,再向右跳两棵树。而对于卡片(2, 2, 4),猴子则怎么也不可能跳到它左边相邻的香蕉树上。

当确定A和B后,则一共可以有B^A张不同的卡片。问题是,在这所有的卡片中,有多少张可以让猴子完成任务。

 

Input

第1行k,表示有k组测试数据,k<=100
第2至k+1行,每行两个自然数A和B,以一个空格分开 (A<= 10 , B <= 20)。

 

Output

共k行,每行的数字代表每组数据中,可以让猴子跳到它左边相邻香蕉树的卡片数。

 

Sample Input

3
2 3
4 8
5 13

 

Sample Output

8
3840
371292

 

给你两个正整数n,m,让你求长度为n+1的满足条件的一个等式:a[1]*x1+a[2]*x2+a[3]*x3+...+a
*xn+a[n+1]*x(n+1)=1 (0<=a[i]<=m&&a[n+1]=m)


让你求一共有多少种情况满足这个条件。

要使得a[1]*x1+a[2]*x2+a[3]*x3+...+a
*xn+a[n+1]*m=1 (0<=a[i]<=m),那么a[1],a[2],a[3]....a[n+1]的最大公约数为1.


要解决此题,你需要知道的知识有扩展欧几里得,鸽巢原理,以及递归求所有的排列组合。

例如:n=2,m=360 

360=3^2*2^3*5  所有不满足条件的数列,最大公约数是360质因子的乘积,只要将这些组合去掉,就是要求的答案(不懂的慢慢揣摩)


那么就要先求出m的所有质因子,然后求出总的排列组合的个数,即题目中说的M^N,最后根据鸽巢原理求得最后答案。

公式为:ans=M^N-(有奇数个公因数的n元组)+(有偶数个公因数的n元组)。拿上面的例子来说就是

ans=m^n-(有公因数2的n元组)- (有公因数3的n元组)- (有公因数5的n元组)+ (有公因数2,3的n元组) +(有公因数2,5的n元组)+ (有公因数3,5的n元组)- (有公因数2,3,5的n元组).

有公因数d的n元组,每个位置上有 (m/d)个选择(1 ~ m里面有m/d个d的倍数),根据乘法原理,可以得出有公因数d的n元组有 (m/d)^n 个.
//400K    0MS
#include<stdio.h>
#define M 130007
long long num[M],s[M];
long long n,m,total,per;
void sum_factor()//分解质因子,存在num里面
{
total=0;
long long t=m;
for(int i=2;i*i<=t;i++)
{
if(t%i==0)num[total++]=i;
while(t%i==0)t/=i;
}
if(t!=1)num[total++]=t;
}
long long pow(long long x,long long y)//求x^y
{
long long k=x;
for(long long i=1;i<y;i++)
x*=k;
return x;
}
void dfs(long long a,long long b,long long c)//a在数组中的起始位置,b含的个数,c公共质因子的个数
{
if(b==c)
{
long long t=m;
//printf("(");
for(long long i=0;i<c;i++)
{
//printf("%d ",s[i]);
t/=s[i];//t表示每位上有几个包含质因子的数
}
//printf(")\n");
per+=pow(t,n);//总共有多少个
}
else
{
for(long long i=a;i<total;i++)//递归回溯求解所有排列组合
{
s=num[i];
dfs(i+1,b+1,c);
}
}
}
int main()
{
int k;
scanf("%d",&k);
while(k--)
{
scanf("%I64d%I64d",&n,&m);
sum_factor();
long long ans=pow(m,n);
for(long long i=1;i<=total;i++)
{
per=0;
dfs(0,0,i);
if(i%2)ans-=per;//如果有奇数个公因数的n元组就相减
else ans+=per;//如果有奇数个公因数的n元组就相加
}
printf("%I64d\n",ans);
}
return 0;
}


携程全球数据中心建设

[b]Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 725    Accepted Submission(s): 307


Problem Description

携程为了扩展全球在线旅游业务,决定在全球建设多数据中心,以便提高网站的访问速度和容灾处理。
为了实现每个数据中心的数据能互通,数据中心之间需要通过光纤连接。为了节约光纤成本,我们计划采用点对点方式来达到最终各个数据中心的数据互通,每个数据中心本身都可以作为数据中转站。做为全球多数据中心设计者,您需要知道最短的光纤总长度,来把所有的数据中心都实现互通。假设地球是个圆球,且表面是平滑的,并且没有任何阻碍物(河流,山脉)。

输入数据是一组数据中心的经纬度
纬度: -90° 到 +90°
经度: -180° 到 +180°
(圆周率pi= 3.14159265358979323846)

 

Input

第一行第一个整数N(1≤N≤100),表示有多少个用例. 每个用例包含了:
第一行,小数D(1≤D≤1,000,000),表面圆球的直径(公里).
第二行,小数L(1≤L≤1,000,000) 光纤总长度 (公里).
第三行,整数C(1≤C≤100) ,表示数据中心的数量.
接下来的C行, 每行有2个形如"X Y"的小数,表示每个数据中心的纬度(-90≤X≤90)和经度 (-180≤Y≤180).

 

Output

每个用例输出一行. 如果光纤长度L足够连接所有数据中心,输出"Y", 否则输出"N"。

 

Sample Input

2
12742
5900
3
51.3 0
42.5 -75
48.8 3
12742
620
2
30.266 97.75
30.45 91.1333

 

Sample Output

Y
N

如何通过地球上两点上的经维度求他们的距离公式?
设球的半径为R,并且假设东经为正,西经为负,北纬为正,南纬为负。
则A(x,y)坐标可表示为(R*cosy*cosx, R*cosy*sinx, R*siny)
B(a,b)坐标可表示为(R*cosb*cosa, R*cosb*sina, R*sinb)
AB两点的的球面距离为:R*(arccos(cosb*cosy*cos(a-x)+sinb*siny))
最后直接最小生成树即可。
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MAX 99999999
const double pi=3.14159265358979323846;
double g[110][110],lgtd[110],lttd[110];

int c;
void init()
{
for(int i=1;i<107;i++)
for(int j=1;j<107;j++)
g[i][j]=MAX;
}
double prime()
{
double low[110];
int flag[110];
memset(flag,0,sizeof(flag));
for(int i=1; i<=c; i++)
{
low[i]=g[1][i];
}
double count=0;
flag[1]=1;
for(int i=1; i<c; i++)
{
double min=MAX+1;
int k;
for(int j=1; j<=c; j++)
{
if(flag[j]==0&&min>low[j])
{
min=low[j];
k=j;
}
}
flag[k]=1;
count+=low[k];
for(int j=1; j<=c; j++)
{
if(flag[j]==0&&low[j]>g[j][k])
{
low[j]=g[j][k];
}
}
}
return count;
}
int main()
{
int t;
double d,l,lgtd[110],lttd[110];
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%d",&d,&l,&c);
for(int i=1;i<=c;i++)
{
scanf("%lf%lf",<td[i],&lgtd[i]);
//弧度=角度*π/180
lgtd[i]=lgtd[i]*pi/180;
lttd[i]=lttd[i]*pi/180;
}
d/=2;
for(int i=1;i<=c;i++)
for(int j=1;j<=c;j++)
{
if(i!=j)
g[i][j]=d*acos(cos(lttd[j])*cos(lttd[i])*cos(lgtd[i]-lgtd[j])+sin(lttd[i])*sin(lttd[j]));
}
double ans=prime();
if(ans>l)printf("N\n");
else printf("Y\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: