2014编程之美初赛第一场

题目1 : 焦距

时间限制:2000ms
单点时限:1000ms
内存限制:256MB

描述

一般来说,我们采用针孔相机模型,也就是认为它用到的是小孔成像原理。

在相机坐标系下,一般来说,我们用到的单位长度,不是“米”这样的国际单位,而是相邻像素的长度。而焦距在相机坐标系中的大小,是在图像处理领域的一个非常重要的物理量。

假设我们已经根据相机参数,得到镜头的物理焦距大小(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\n" :: "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 : 树

时间限制: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


比赛时想到正解前,交了一发爆搜,最后大数据都能过,数据也够弱的,囧。

后来在比赛中想到如下思路,最后也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\n" :: "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 : 活动中心

时间限制: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

 

解题思路:

 三分,跟去年编程之美这题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;
}

  

 

posted @ 2014-04-19 17:29  yejinru  阅读(356)  评论(0编辑  收藏  举报