题目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
解题思路:
为了方便,我们可以用stringstream字符串流进行string流的读入。
我们需要用long double避免double不够位数的问题。
格式输出:
cout<<setiosflags(ios::fixed)<<setprecision(2)<<ans<<"px"<<endl;
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <complex>
#include <fstream>
#include <iostream>
#include <algorithm>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define debug puts("yejinru")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(int i=0;i<(int)vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
#define lson rt<<1
#define rson rt<<1|1
#define SZ(x) x.size()
/*
#pragma comment(linker, "/STACK:1024000000,1024000000")
int ssize = 256 << 20; // 256MB
char *ppp = (char*)malloc(ssize) + ssize;
__asm__("movl %0, %%esp
" :: "r"(ppp) );
*/
char IN;
bool NEG;
inline void Int(int &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
}
inline void LL(ll &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
}
/******** program ********************/
long double in(string a){
int id = 1;
if( !isdigit(a[ a.size()-2 ]) )
id = 2;
stringstream ccin(a.substr(0,a.size()-id));
long double d;
ccin>>d;
if(id==1)
d *= 1000;
else{
id = a.size()-2;
if(a[id]=='d')
d *= 100;
else if(a[id]=='c')
d *= 10;
else if(a[id]=='m')
d *= 1;
else if(a[id]=='u')
d *= 0.001;
else
d /= 1000*1000;
}
return d;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif
int ncase,cnt = 0;
RD(ncase);
while(ncase--){
string a,b,c;
cin>>a>>b>>c;
long double x = in(a);
long double y = in(b);
stringstream dd(c.substr(0,c.size()-2));
long double z;
dd>>z;
long double ans = x/y*z;
printf("Case %d: ",++cnt);
cout<<setiosflags(ios::fixed)<<setprecision(2)<<ans<<"px"<<endl;
}
return 0;
}
题目2 : 树
描述
有一个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
比赛时想到正解前,交了一发爆搜,最后大数据都能过,数据也够弱的,囧。
后来在比赛中想到如下思路,最后也A了。
解题思路如下:
首先遍历整棵树,记录下每个节点的高度。
对于询问(x,l,r,delta),我们把该操作(l,r,delta)放进vector[x]中。
最后,我们遍历一遍整棵树,对于节点x,我们用差分数列、树状数组或线段树进行维护。
差分数列维护的话:
先遍历一遍vector[x],把操作(l,r,delta)添加到深度为[l,r]的区间
foreach(i,vec[x]){ node now = vec[x][i]; int l = now.l; int r = now.r; ll val = now.val; a[l] += val; a[r+1] -= val; }
因为是dfs,所以递归到下一层时,直接累和即为当前节点的值,累和:
a[depth] += a[depth-1];
然后递归遍历x节点的子节点
消除当前节点对其他非子节点的影响,最后把加上的给减掉:
a[depth] = (a[depth]-a[depth-1]+3LL*MOD)%MOD; foreach(i,vec[x]){ node now = vec[x][i]; int l = now.l; int r = now.r; ll val = now.val; a[l] -= val; a[r+1] += val; }
最后代码如下:
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <complex>
#include <fstream>
#include <iostream>
#include <algorithm>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define debug puts("yejinru")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(int i=0;i<(int)vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
#define lson rt<<1
#define rson rt<<1|1
#define SZ(x) x.size()
/*
#pragma comment(linker, "/STACK:1024000000,1024000000")
int ssize = 256 << 20; // 256MB
char *ppp = (char*)malloc(ssize) + ssize;
__asm__("movl %0, %%esp
" :: "r"(ppp) );
*/
char IN;
bool NEG;
inline void Int(int &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
}
inline void LL(ll &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
}
/******** program ********************/
const int MAXN = 1e5+5;
struct node{
int l,r;
ll val;
node(){}
node(int _l,int _r,ll _val){
l = _l;
r = _r;
val = _val;
}
};
vector<int> adj[MAXN];
vector< node > vec[MAXN];
ll delta[MAXN];
int dep[MAXN];
const int MOD =1000000007; // 10^9 + 7
const int MAGIC= 12347;
void dfs_init(int x,int d){ // 初始化每个节点的深度
dep[x] = d;
foreach(i,adj[x])
dfs_init(adj[x][i],d+1);
}
ll a[MAXN];
void dfs(int x,int depth){
foreach(i,vec[x]){
node now = vec[x][i];
int l = now.l;
int r = now.r;
ll val = now.val;
a[l] += val; // 添加
a[r+1] -= val;
}
a[depth] = (a[depth]+a[depth-1]+3LL*MOD)%MOD; // 差分数列
delta[x] = a[depth];
foreach(i,adj[x])
dfs(adj[x][i],depth+1);
a[depth] = (a[depth]-a[depth-1]+3LL*MOD)%MOD;
foreach(i,vec[x]){
node now = vec[x][i];
int l = now.l;
int r = now.r;
ll val = now.val;
a[l] -= val; // 消除对后面影响
a[r+1] += val;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif
int ncase,cnt = 0;
RD(ncase);
while(ncase--){
printf("Case %d: ",++cnt);
int n,pa,q;
RD(n);
rep1(i,n){
adj[i].clear();
vec[i].clear();
}
memset(delta,0,sizeof(delta));
for(int i=2;i<=n;i++){
RD(pa);
adj[pa].pb(i);
}
dfs_init(1,1);
RD(q);
int l,r,x,d;
while(q--){
RD4(x,l,r,d);
vec[x].pb( node(l,r,d) );
}
memset(a,0,sizeof(a));
dfs(1,1);
ll ans = 0;
rep1(i,n)
ans = (ans*MAGIC+delta[i]+3LL*MOD)%MOD;
cout<<ans<<endl;
}
return 0;
}
题目3 : 活动中心
描述
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
解题思路:
三分,跟去年编程之美这题2013編程之美 集会 三分基本一样。注意下迭代次数。
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define lx(x) (x<<1)
#define rx(x) (x<<1|1)
#define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
/******** program ********************/
const int MAXN = 1e5+5;
const int INF = 1e8;
struct node{
double x,y;
}p[MAXN];
int n;
long double dis(long double x,long double y){
return sqrt( x*x+y*y );
}
long double cal(long double now){
long double tmp = 0;
rep(i,n)
tmp += dis(p[i].x-now,p[i].y);
return tmp;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif
int ncase;
RD(ncase);
rep1(Ncase,ncase){
printf("Case %d: ",Ncase);
RD(n);
long double L = INF,R = -INF;
rep(i,n){
scanf("%lf%lf",&p[i].x,&p[i].y);
L = min(L,(long double)p[i].x);
R = max(R,(long double)p[i].x);
}
long double l = 0,r = 1;
long double px1,px2;
rep(step,50){
long double m1 = (2*l+r)/3;
long double m2 = (l+2*r)/3;
px1 = L*(1-m1)+R*m1;
px2 = L*(1-m2)+R*m2;
long double tmp = cal(px1);
long double ret = cal(px2);
if(tmp>ret)
l = m1;
else
r = m2;
}
if(px1<0&&fabs(px1)<1e-9) // 判斷是否會出現-0.000000
px1 *= -1.0;
cout<<setiosflags(ios::fixed)<<setprecision(8)<<px1<<endl;
}
return 0;
}