编程之美初赛第一场
题目1 : 焦距
描述
一般来说,我们采用针孔相机模型,也就是认为它用到的是小孔成像原理。
在相机坐标系下,一般来说,我们用到的单位长度,不是“米”这样的国际单位,而是相邻像素的长度。而焦距在相机坐标系中的大小,是在图像处理领域的一个非常重要的物理量。
假设我们已经根据相机参数,得到镜头的物理焦距大小(focal length),和相机胶片的宽度(CCD width),以及照片的横向分辨率(image width),则具体计算公式为:
Focal length in pixels = (image width in pixels) * (focal length on earth) / (CCD width on earth)
比如说对于Canon PowerShot S100, 带入公式得
Focal length in pixels = 1600 pixels * 5.4mm / 5.27mm = 1639.49 pixels
现在,请您写一段通用的程序,来求解焦距在相机坐标系中的大小。
输入
多组测试数据。首先是一个正整数T,表示测试数据的组数。
每组测试数据占一行,分别为
镜头的物理焦距大小(focal length on earth)
相机胶片的宽度(CCD width on earth)
照片的横向分辨率大小(image width in pixels),单位为px。
之间用一个空格分隔。
输出
每组数据输出一行,格式为“Case X: Ypx”。 X为测试数据的编号,从1开始;Y为焦距在相机坐标系中的大小(focallength in pixels),保留小数点后2位有效数字,四舍五入取整。
数据范围
对于小数据:focal length on earth和CCD width on earth单位都是毫米(mm)
对于大数据:长度单位还可能为米(m), 分米(dm), 厘米(cm), 毫米(mm), 微米(um),纳米(nm)
- 样例输入
-
2 5.4mm 5.27mm 1600px 5400um 0.00527m 1600px
- 样例输出
-
Case 1: 1639.47px Case 2: 1639.47px
1 #include <stdio.h> 2 #include <string.h> 3 double cmp(char s[]) 4 { 5 if(strcmp(s,"mm")==0) 6 return 1.0; 7 else if (strcmp(s,"m")==0) 8 return 1000.0; 9 else if (strcmp(s,"cm")==0) 10 return 10.0; 11 else if (strcmp(s,"dm")==0) 12 return 100.0; 13 else if (strcmp(s,"um")==0) 14 return 0.001; 15 else if (strcmp(s,"nm")==0) 16 return 0.000001; 17 } 18 int main() 19 { 20 int t; 21 scanf("%d",&t); 22 for (int i = 1; i <= t; i++) 23 { 24 double l,w,m; 25 char s1[5],s2[5],s3[5]; 26 scanf("%lf%s %lf%s %lf%s",&l,s2,&w,s3,&m,s1); 27 l = l*cmp(s2); 28 w = w*cmp(s3); 29 double ans = m*l/w; 30 printf("Case %d: %.2fpx\n",i,ans); 31 } 32 return 0; 33 }
题目2 : 树
时间限制:4000ms单点时限:2000ms内存限制:256MB描述
有一个N个节点的树,其中点1是根。初始点权值都是0。
一个节点的深度定义为其父节点的深度+1,。特别的,根节点的深度定义为1。
现在需要支持一系列以下操作:给节点u的子树中,深度在l和r之间的节点的权值(这里的深度依然从整个树的根节点开始计算),都加上一个数delta。
问完成所有操作后,各节点的权值是多少。
为了减少巨大输出带来的开销,假设完成所有操作后,各节点的权值是answer[1..N],请你按照如下方式计算出一个Hash值(请选择合适的数据类型,注意避免溢出的情况)。最终只需要输出这个Hash值即可。
MOD =1000000007; // 10^9 + 7
MAGIC= 12347;
Hash =0;
For i= 1 to N do
Hash = (Hash * MAGIC + answer[i]) mod MOD;
EndFor
输入
第一行一个整数T (1 ≤ T ≤ 5),表示数据组数。
接下来是T组输入数据,测试数据之间没有空行。
每组数据格式如下:
第一行一个整数N (1 ≤ N ≤ 105),表示树的节点总数。
接下来N - 1行,每行1个数,a (1 ≤ a ≤ N),依次表示2..N节点的父亲节点的编号。
接下来一个整数Q(1 ≤ Q ≤ 105),表示操作总数。
接下来Q行,每行4个整数,u, l, r, delta (1 ≤ u ≤ N, 1 ≤ l ≤ r ≤ N, -109 ≤ delta ≤ 109),代表一次操作。
输出
对每组数据,先输出一行“Case x: ”,x表示是第几组数据,然后接这组数据答案的Hash值。
数据范围
小数据:1 ≤ N, Q ≤ 1000
大数据:1 ≤ N, Q ≤ 105
样例解释
点1的子树中有1,2,3三个节点。其中深度在2-3之间的是点2和点3。
点2的子树中有2,3两个节点。其中没有深度为1的节点。
所以,执行完所有操作之后,只有2,3两点的权值增加了1。即答案是0 1 1。再计算对应的Hash值即可.
- 样例输入
-
1 3 1 2 2 1 2 3 1 2 1 1 1
- 样例输出
-
Case 1: 12348
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 using namespace std; 5 const int N=100005; 6 const long long MOD=1000000007; 7 vector<int>v[N]; 8 int deg[N],ans[N]; 9 int n; 10 void dfs(int u,int d)//搜索处理每一点的度 11 { 12 deg[u] = d; 13 for (int i = 0; i < v[u].size(); i++) 14 { 15 dfs(v[u][i],d+1); 16 } 17 } 18 void dfs2(int u,int l,int r,int c)//搜索改变区间[l,r]的度 19 { 20 if (deg[u] > r) 21 return; 22 if (deg[u]>=l) 23 ans[u]+=c; 24 for (int i = 0; i < v[u].size(); i++) 25 { 26 dfs2(v[u][i],l,r,c); 27 } 28 } 29 long long hash() 30 { 31 long long Hash = 0; 32 int MAGIC= 12347; 33 for (int i = 1; i <= n; i++) 34 Hash = (Hash * MAGIC + ans[i]) % MOD; 35 return Hash; 36 } 37 int main() 38 { 39 int t,o = 0; 40 scanf("%d",&t); 41 while(t--) 42 { 43 o++; 44 int x; 45 scanf("%d",&n); 46 for (int i = 0; i <= n; i++) 47 v[i].clear(); 48 memset(deg,0,sizeof(deg)); 49 memset(ans,0,sizeof(ans)); 50 for (int i = 2; i <= n; i++) 51 { 52 scanf("%d",&x); 53 v[x].push_back(i); 54 } 55 dfs(1,1); 56 int Q; 57 scanf("%d",&Q); 58 int u,l,r,c; 59 long long Hash; 60 while(Q--) 61 { 62 scanf("%d%d%d%d",&u,&l,&r,&c); 63 dfs2(u,l,r,c); 64 Hash = hash(); 65 } 66 printf("Case %d: %lld\n",o,Hash); 67 } 68 return 0; 69 }
题目3 : 活动中心
时间限制:12000ms单点时限:6000ms内存限制:256MB描述
A市是一个高度规划的城市,但是科技高端发达的地方,居民们也不能忘记运动和锻炼,因此城市规划局在设计A市的时候也要考虑为居民们建造一个活动中心,方便居住在A市的居民们能随时开展运动,锻炼强健的身心。
城市规划局希望活动中心的位置满足以下条件:
1. 到所有居住地的总距离最小。
2. 为了方便活动中心的资源补给和其他器材的维护,活动中心必须建设在A市的主干道上。
为了简化问题,我们将A市摆在二维平面上,城市的主干道看作直角坐标系平的X轴,城市中所有的居住地都可以看成二维平面上的一个点。
现在,A市的城市规划局希望知道活动中心建在哪儿最好。
输入
第一行包括一个数T,表示数据的组数。
接下来包含T组数据,每组数据的第一行包括一个整数N,表示A市共有N处居住地
接下来N行表示每处居住地的坐标。
输出
对于每组数据,输出一行“Case X: Y”,其中X表示每组数据的编号(从1开始),Y表示活动中心的最优建造位置。我们建议你的输出保留Y到小数点后6位或以上,任何与标准答案的绝对误差或者相对误差在10-6以内的结果都将被视为正确。
数据范围
小数据:1 ≤ T ≤ 1000, 1 ≤ N ≤ 10
大数据:1 ≤ T ≤ 10, 1 ≤ N ≤ 105
对于所有数据,坐标值都是整数且绝对值都不超过106
样例解释
样例1:活动中心的最优建造位置为(1.678787, 0)
- 样例输入
-
1 3 1 1 2 2 3 3
- 样例输出
-
Case 1: 1.678787
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int INF=1<<28; 8 const int N=100005; 9 const double eps=1e-8; 10 int n; 11 struct node 12 { 13 double x,y; 14 }f[N]; 15 int max = INF; 16 double dis(double x,double y,double xx) 17 { 18 return sqrt((x-xx)*(x-xx)+y*y); 19 } 20 double ternarySearch(double l,double r)//三分 21 { 22 while(r-l>eps) 23 { 24 double sum1 = 0,sum2 = 0; 25 double ll=(2*l+r)/3; 26 double rr=(l+2*r)/3; 27 for (int i = 1;i <= n; i++) 28 sum1+=dis(f[i].x,f[i].y,ll); 29 for (int i = 1;i <= n; i++) 30 sum2+=dis(f[i].x,f[i].y,rr); 31 if (sum1 > sum2) 32 l = ll; 33 else 34 r = rr; 35 36 } 37 return l; 38 } 39 int main() 40 { 41 int t; 42 int o = 0; 43 printf("%d\n",INF); 44 scanf("%d",&t); 45 while(t--) 46 { 47 o++; 48 scanf("%d",&n); 49 double l = INF,r = -INF; 50 for (int i = 1;i <= n; i++) 51 { 52 scanf("%lf%lf",&f[i].x,&f[i].y); 53 if (l > f[i].x) 54 l = f[i].x; 55 if (r < f[i].y) 56 r = f[i].y; 57 } 58 double ans = ternarySearch(l,r); 59 printf("Case %d: %.7f\n",o,ans); 60 61 } 62 return 0; 63 }