组队练习 2011年福州全国邀请赛

A 水题。

B 计算几何求重心,枚举对称点。

#include <string.h>

#include <algorithm>

#include <stdio.h>

#include <cmath>

#include <iostream>

using namespace std;

#define maxn 600

#define eps 1e-6

bool zero(double a) {return (fabs(a)<eps?1:0);}

struct point{

    double x,y;

}po[maxn],center;

int n;

struct line{

    point a,b;

};

double cross1(point &a,point &b,point &c){

    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);

}

double cross(point p1,point p2,point p0){

    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);

}

point intersection(line u,line v){

    point ret=u.a;

    double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));

    ret.x+=(u.b.x-u.a.x)*t;

    ret.y+=(u.b.y-u.a.y)*t;

    return ret;

}

point barycenter(point a,point b,point c){

    line u,v;

    u.a.x=(a.x+b.x)/2;

    u.a.y=(a.y+b.y)/2;

    u.b=c;

    v.a.x=(a.x+c.x)/2;

    v.a.y=(a.y+c.y)/2;

    v.b=b;

    return intersection(u,v);

}

point barycenter(int n,point *p){

    point ret,t;

    double t1=0,t2;

    int i;

    ret.x=ret.y=0;

    for(i=1;i<n-1;i++){

        if(fabs(t2=cross(p[0],p[i],p[i+1]))>eps){

            t=barycenter(p[0],p[i],p[i+1]);

            ret.x+=t.x*t2;

            ret.y+=t.y*t2;

            t1+=t2;

        }

    }

    if(fabs(t1)>eps)

        ret.x/=t1,ret.y/=t1;

    return ret;

}

double dmult(point &a,point &b){

    return a.x*b.x+a.y*b.y;

}

double dmult(double a,double b,double c,double d){

    return a*c+b*d;

}

bool is_ok(int l,int r,int a,int b){

    if(r<l)return true;

    point temp,t;

    while(l<r){

        temp.x=(po[l].x+po[r].x)/2;

        temp.y=(po[l].y+po[r].y)/2;

         if(!zero(dmult(po[l].x-po[r].x,po[l].y-po[r].y,temp.x-center.x,temp.y-center.y)))

            return false;

         l++,r--;

    }

    temp.x=(po[a].x+po[b].x)/2;

    temp.y=(po[a].y+po[b].y)/2;

    if(l==r)

    return zero(cross(temp,center,po[l]));

    return true;

}

bool sovle(){

    int i,k;

    point temp;

    for(i=1;i<n;i++){

        temp.x=(po[0].x+po[i].x)/2;

        temp.y=(po[0].y+po[i].y)/2;

        if(zero(dmult(po[i].x-po[0].x,po[i].y-po[0].y,temp.x-center.x,temp.y-center.y))){

                if(is_ok(1,i-1,0,i)&& is_ok(i+1,n-1,0,i))

                return true;

        }

    }

     for(i=2;i<n;i++){

        temp.x=(po[1].x+po[i].x)/2;

        temp.y=(po[1].y+po[i].y)/2;

        if(zero(dmult(po[i].x-po[1].x,po[i].y-po[1].y,temp.x-center.x,temp.y-center.y))){

            //printf("HHHH%lf %lf\n",po[i].x,po[i].y);

                if(is_ok(2,i-1,1,i)&& is_ok(i+1,n,1,i))

                return true;

        }

    }

    return false;

}

int main(){

    int i,j,k,t,cas=0;

    scanf("%d",&t);

    while(t--){



        scanf("%d",&n);

        for(i=0;i<n;i++)

        scanf("%lf%lf",&po[i].x,&po[i].y);

        k=1;

        for(i=2;i<n;i++){

            if(zero(cross(po[k-1],po[k],po[i])))

            po[k]=po[i];

            else po[++k]=po[i];

        }

        k++;

        if(zero(cross(po[0],po[k-1],po[k-2])))

        k--;

        if(zero(cross(po[k-1],po[0],po[1]))){

                for(i=1;i<k;i++)

                 po[i-1]=po[i];

                 k--;

        }

        n=k;

        printf("Case %d: ",++cas);

        if(k<=2){

            printf("YES\n");

            continue;

        }

        po[n]=po[0];

        center=barycenter(n,po);

        if(sovle())

            printf("YES\n");

        else

            printf("NO\n");

    }

    return 0;

}

C 数学题。

import java.math.*;

import java.math.BigDecimal;

import java.util.*;

public class Main {

    public static void main(String arg[]){

        BigDecimal a,b,c,x,y,z,d,an,ans;

        Scanner cin=new Scanner(System.in);

        int t=1,tt;

        tt=cin.nextInt();

        an=BigDecimal.valueOf(32);

        while(tt-->0){

            a=cin.nextBigDecimal();

            b=cin.nextBigDecimal();

            if(a.compareTo(b)>0){

                c=a.subtract(b);

                d=b;

                ans=a;

            }else{

                c=b.subtract(a);

                d=a;

                ans=b;

            }

            if(c.compareTo(an)<0){

                double s=c.doubleValue();

                s=Math.pow(2.0,s)+1;

                s=Math.log(s)/Math.log(2.0);

                ans=d;

                ans=ans.add(BigDecimal.valueOf(s));

            }

            ans = ans.setScale(9, BigDecimal.ROUND_HALF_UP);

            System.out.println("Case "+t+": "+ans);

            t++;

        }

    }

}

D 数学

#include<iostream>

#include<cmath>

#include<cstring>

#include<string>

#include<algorithm>

#include<iomanip>

#include<cstdio>

#define ll long long

#define M 1000001

#define mod 1000000007

using namespace std;

ll an[M];

double p[M];

void init()

{

    an[0]=0;an[1]=1;

    p[0]=0;p[1]=1;

    ll t=1;

    for(int i=2;i<M;i++){

        an[i]=(i*an[i-1]%mod+t)%mod;

        t=(t*i)%mod;

        p[i]=p[i-1]+1.0/(double)i;

    }

}

int main()

{

    int t,n,ca=0;

    init();

    scanf("%d",&t);

    while(t--){

        scanf("%d",&n);

        printf("Case %d: %I64d %.6lf\n",++ca,an[n],p[n]);

    }

    return 0;

}

E 树形DP。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define Maxn 100010

#define LL __int64

using namespace std;

int son[Maxn],vi[Maxn],head[Maxn],e;

struct Edge{

    int u,v,next;

    LL val;

}edge[Maxn*3];

LL ans,sum;

void add(int u,int v,LL val)

{

    edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].next=head[u],head[u]=e++;

    edge[e].u=v,edge[e].v=u,edge[e].val=val,edge[e].next=head[v],head[v]=e++;

}

void init()

{

    memset(son,0,sizeof(son));

    memset(vi,0,sizeof(vi));

    memset(head,-1,sizeof(head));

    e=0;

}

void dfs(int u)

{

    int i,v;

    son[u]=1;

    vi[u]=1;

    for(i=head[u];i!=-1;i=edge[i].next){

        v=edge[i].v;

        //cout<<u<<" "<<v<<" ";

        if(vi[v]) continue;

        dfs(v);

        //cout<<son[v]<<" "<<sum<<" "<<edge[i].val<<endl;

        ans+=son[v]*(sum-son[v])*2*edge[i].val;

        son[u]+=son[v];

    }

}

int main()

{

    int t,n,a,b,i,j,Ca=0;

    LL c;

    scanf("%d",&t);

    while(t--){

        init();

        scanf("%d",&n);

        for(i=1;i<n;i++){

            scanf("%d%d%I64d",&a,&b,&c);

            a++,b++;

            add(a,b,c);

        }

        ans=0;

        sum=n;

        dfs(1);

        printf("Case %d: %I64d\n",++Ca,ans);

    }

    return 0;

}

F 是个最大匹配

#include<iostream>

#include<algorithm>

#include<cstring>

#include<cstdio>

#define Maxn 110

using namespace std;

int match[Maxn],n,m;

bool g[Maxn][Maxn],vi[Maxn];

int dfs(int u)

{

    int i;

    for(i=1;i<=m;i++){

        if(!vi[i]&&g[u][i]){

            vi[i]=1;

            if(match[i]==-1||dfs(match[i])){

                match[i]=u;

                return true;

            }

        }

    }

    return false;

}

int main()

{

    int t,e,i,j,u,v,Ca=0;

    scanf("%d",&t);

    while(t--){

        scanf("%d%d%d",&n,&m,&e);

        memset(g,1,sizeof(g));

        for(i=1;i<=e;i++){

            scanf("%d%d",&u,&v);

            g[u][v]=0;

        }

        memset(match,-1,sizeof(match));

        int ans=0;

        for(i=1;i<=n;i++){

            memset(vi,0,sizeof(vi));

            if(dfs(i))

                ans++;

        }

        printf("Case %d: %d\n",++Ca,ans);

    }

    return 0;

}

 

 先O(n)预处理出ri[i][j],le[i][j],分别表示第i个位置向右边移动出j个空格需要的步数,表示第i个位置向左边移动出j个空格需要的步数。

然后枚举间隙处,二分判段最大间隔。

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#define Maxn 710

#define inf 100000000

using namespace std;

int ri[Maxn][Maxn],le[Maxn][Maxn],n,m;

char str[Maxn];

bool OK(int pos,int x)

{

    int i,j,cnt=inf;

    if(pos==1) {

        cnt=min(cnt,ri[pos][x]);

        return cnt<=m;

    }

    for(i=0;i<=n;i++){

        if(i>x) break;

        cnt=min(cnt,ri[pos][i]+le[pos-1][x-i]);

    }

    //cout<<pos<<" "<<x<<" "<<cnt<<" "<<m<<endl;

    return cnt<=m;

}

int main()

{

    int t,i,j,ze,Ca=0;

    scanf("%d",&t);

    while(t--){

        for(i=1;i<Maxn;i++){

            for(j=1;j<Maxn;j++){

                ri[i][j]=le[i][j]=inf;

            }

        }

        ze=0;

        scanf("%d%d%s",&n,&m,str);

        if(str[0]=='0') le[1][1]=0,ze=1;

        for(i=1;i<n;i++){

            if(str[i]=='0') ze++;

            for(j=1;j<=n;j++){

                if(le[i][j-1]>=inf) break;

                if(str[i]=='1')

                    le[i+1][j]=le[i][j]+j;

                else

                    le[i+1][j]=le[i][j-1];

            }

        }

        if(str[n-1]=='0') ri[n][1]=ri[n+1][1]=0;

        for(i=n-1;i>=1;i--){

            for(j=1;j<=n;j++){

                if(ri[i+1][j-1]>=inf) break;

                if(str[i-1]=='1')

                    ri[i][j]=ri[i+1][j]+j;

                else

                    ri[i][j]=ri[i+1][j-1];

            }

        }

        int f=0;

        int ans=0,l,r,mid;

        for(i=1;i<=n;i++){

            if(str[i-1]=='0'){

                l=0;r=ze;

                while(l+1<r){

                    mid=(l+r)>>1;

                    if(OK(i,mid))

                        l=mid;

                    else

                        r=mid;

                }

                ans=max(ans,l);

                if(OK(i,r))

                    ans=max(ans,r);

            }

        }

        printf("Case %d: %d\n",++Ca,ans);

    }

    return 0;

}

 

 

你可能感兴趣的:(组队练习 2011年福州全国邀请赛)