2014 BUPT 新生排位赛05

来源:互联网 发布:免费网络短信平台 编辑:程序博客网 时间:2024/05/23 19:20

A 平方的平均值

题目链接:http://code.bupt.edu.cn/problem/p/442/

思路:超级大水题了,我都无语了,要注意到xi可能取负数,然后就没什么问题了,比赛的时候没有注意到一个int转long long

先上wa的代码:

#include <iostream>#include <cstring>#include <cstdlib>#include<cstdio>#include <algorithm>#include <vector>#define INF 10000000000#define eps 1e-9using namespace std;const int MAX_E=200100;const int MAX_N=10000005; int main(){    int n,a;//这个地方应该开long long     long long mid;    while(scanf("%d",&n)!=EOF){        if(n==0){            printf("0\n");            continue;        }        scanf("%d",&a);        mid=a*a;        for(int i=1;i<n;i++){            scanf("%d",&a);            if(a*a<mid) mid=a*a;        }        printf("%lld\n",mid);    }    return 0;}
A的代码:

#include <iostream>#include <cstring>#include <cstdlib>#include<cstdio>#include <algorithm>#include <vector>#define INF 10000000000#define eps 1e-9using namespace std;const int MAX_E=200100;const int MAX_N=10000005; int main(){    int n;    long long a;    long long mid;    while(scanf("%d",&n)!=EOF){        if(n==0){            printf("0\n");            continue;        }        cin>>a;        mid=a*a;        for(int i=1;i<n;i++){            cin>>a;            if(a*a<mid) mid=a*a;        }        printf("%lld\n",mid);    }    return 0;}

B 立方体

题目链接:http://code.bupt.edu.cn/problem/p/431/

大致思路:先找到与待求点对应的点(这个点到其他点的距离和最短),再找得到其相邻的三个点(这三点到这个点的距离相等),再通过一个向量加法就可以求出来待求点。

比赛的时候剩的时间太少了,当时脑子还特别乱就没做出来,后来做的时候wa了好多次,这主要是因为dis用了double,应该不算他的开方,直接平方来比较。

code:

#include <iostream>#include <cstring>#include <cstdlib>#include<cstdio>#include <algorithm>#include <vector>#include <cmath>#define INF 99999999#define eps 1e-9using namespace std;const int MAX_E=200100;const int MAX_N=10; struct pos{int x,y,z;} P[MAX_N];long long tt[MAX_N];int cc[MAX_N];long long dis(pos A,pos B){    long long res;    res=(A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z);    return res;}int main(){    int nn,m,T;    long long midnn;    pos dd;    scanf("%d",&T);    while(T--){        midnn=0;        m=0;        for(int i=0;i<7;i++) scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].z);        memset(tt,0,sizeof(tt));        for(int i=0;i<7;i++){            for(int j=0;j<7;j++){                if(j==i) continue;                tt[i]+=dis(P[i],P[j]);            }            if(midnn==0) {midnn=tt[i];nn=i;}            else if(tt[i]<midnn){                midnn=tt[i];                nn=i;            }        }        midnn=0;        for(int i=0;i<7;i++){            if(i==nn) continue;            if(midnn==0){                midnn=dis(P[nn],P[i]);                cc[m++]=i;            }            else if(midnn==dis(P[nn],P[i])) cc[m++]=i;        }        dd.x=(P[cc[0]].x-P[nn].x)+(P[cc[1]].x-P[nn].x)+(P[cc[2]].x-P[nn].x);        dd.y=(P[cc[0]].y-P[nn].y)+(P[cc[1]].y-P[nn].y)+(P[cc[2]].y-P[nn].y);        dd.z=(P[cc[0]].z-P[nn].z)+(P[cc[1]].z-P[nn].z)+(P[cc[2]].z-P[nn].z);         printf("%d %d %d\n",dd.x+P[nn].x,dd.y+P[nn].y,dd.z+P[nn].z);    }}

C 字符重排

题目链接:http://code.bupt.edu.cn/problem/p/432/

思路:自己想了一种贪心的算法,就是想先把字符串按降序排列,然后再从头开始一个一个取,一开始超时,后来自己有加了一个队列优化,wa,发现了一个无法解决的bug。

看了学长的标程有了一个更好的贪心算法:先统计每个字符出现的次数,如果最大次数大于l(表示字符串的长度)就直接返回-1,之后判断剩余长度是否是奇数,如果是奇数且存在一个字符出现的次数等于剩余长度+1除以二,则此次添加此字符,否则选择一个最靠前的字符添加。

学长的标程写的真是优美,参照的写了一个(太优美了,简洁的不能再简洁了)。

code:

#include<bits/stdc++.h>using namespace std;char a[100005],b[100005];int nn[26]; void solve(){    int l=strlen(a),maxnn=0;    memset(nn,0,sizeof(nn));    for(int i=0;i<l;i++) maxnn=max(maxnn,++nn[a[i]-'a']);    if(maxnn>(l+1)/2){        printf("-1\n");        return ;    }    int pre=-1;    for(int k=0;k<l;k++){        int flag=0,ii=-1;        for(int i=0;i<26;i++){            if(((l-k)&1)&&nn[i]==(l-k+1)/2) flag=1,ii=i;            else if(!flag&&nn[i]&&ii==-1&&i!=pre) ii=i;        }        b[k]=ii+'a';        nn[ii]--;        pre=ii;    }    b[l]='\0';    printf("%s\n",b);}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%s",a);        solve();    }    return 0;}

D   Fibnacci

链接:http://code.bupt.edu.cn/problem/p/433/

思路:因为数据规模比较大,所以直接用递推式肯定超时,给的内存也开不了那么大的数组。就用矩阵快速幂的方法来快速计算递推式。

由于这个还不是裸的 Fibnacci,所以得给式子做一个变形:f(n)=f(n-1)+f(n-2)+n  <=> f(n)+n=f(n-1)+n-1+f(n-2)+n-2+3 <=> Tn=Tn-1+Tn-2+3

再用矩阵快速幂就可以做出来了,取模的时候可能会出现负数的情况(在这个里卡了好长时间),还好最后发现了。

code:

#include <iostream>#include <cstring>#include <cstdlib>#include<cstdio>#include <algorithm>#include <vector>#define INF 10000000000#define eps 1e-9using namespace std;const int MAX_E=200100;const int MAX_N=10000005; typedef vector<long long> a;typedef vector<a> b; const long long M=1000000007; b mul(b &A,b &B){    b C(A.size(),a(B[0].size()));    for(int i=0;i<A.size();i++){        for(int k=0;k<B.size();k++){            for(int j=0;j<B[0].size();j++){                C[i][j]=(C[i][j]+A[i][k]*B[k][j])%M;            }        }    }    return C;} b pow(b A,long long n){    b B(A.size(),a(A.size()));    for(int i=0;i<A.size();i++) B[i][i]=1;    while(n>0){        if(n&1) B=mul(B,A);        A=mul(A,A);        n>>=1;    }    return B;} int main(){    int t;    long long n;    scanf("%d",&t);    b A(3,a(3));    while(t--){        cin>>n;        A[0][0]=A[0][1]=A[0][2]=1;        A[1][0]=1;A[1][1]=A[1][2]=0;        A[2][0]=A[2][1]=0;A[2][2]=1;        A=pow(A,n);        long long res=2*A[1][0]+A[1][1]+3*A[1][2];        if(res<n) res+=M; //防止出现负数!!!        printf("%lld\n",(res-n)%M);    }}


0 0