【题解】BUPT 2015 freshman contest 2

A题裸的求最大连续字串和,我的做法是先求一个前缀和,然后我要求的就是所有s[j]-min(s[i]) i<j,最大的值,然后我可以o(1)的维护min(s[i]),这个算法就是o(n)的了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int s[200100];
int ans;
int main()
{
    int t,ci,ansl,ansr,k,n,x;
    scanf("%d",&t);
    for (int ci=1;ci<=t;ci++)
    {
        memset(s,0,sizeof(s));
        scanf("%d",&n);
        scanf("%d",&s[1]);
        ans=s[1];
        ansl=1;
        ansr=1;
        if (s[1]<0) k=1;
        else k=0;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            s[i]=s[i-1]+x;
            if (s[i]-s[k]>ans) {ans=s[i]-s[k];ansl=k+1;ansr=i;}
            if (s[i]<s[k]) k=i;
        }
        printf("Case %d:\n",ci);
        printf("%d %d %d",ans,ansl,ansr);
        if (ci!=t) printf("\n\n");
        else printf("\n");
    }
    return 0;
}
B 题目因为说了可以每次取任意比例( 比利),所以就直接按照J[i]/f[i] 从大到小选就行。

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<cmath> 
#include<algorithm> 
#include<cstdlib> 
using namespace std; 
struct recc 
{     
     int x,y; 
}rec[200100]; 
int cmp(recc a,recc b) 
{
     return ((double)a.x/a.y)>((double)b.x/b.y); 
} 
int main() 
{
     int n,m;
     double ans=0;
     while (scanf("%d%d",&m,&n))
     {
         ans=0;
         memset(rec,0,sizeof(rec));
         if (m==-1&&n==-1) return 0;
         for (int i=1;i<=n;i++)
             scanf("%d%d",&rec[i].x,&rec[i].y);              
         sort(rec+1,rec+n+1,cmp);
         for (int i=1;i<=n,m!=0;i++)
         {
             if (m>=rec[i].y) ans+=rec[i].x;
             else ans+=(double)(m)/rec[i].y*rec[i].x;
             m=m-min(m,rec[i].y);
         }
         printf("%.3lf\n",ans);
     }
     return 0;
 }


C题的话,因为要找一个矩阵内放一个多米诺骨牌的方案,所以对于每个格子,都有上下左右四中方案,我们利用前缀和的思想,用s[i][j][k]代表以(1,1)为左上角,(i,j)为右下角方向为k的方案数,k=0->3,分别代表上下左右其中一个方向,那么对于选定矩阵,我们可以很容易统计出它如果没有边沿限制的话放一个多米诺骨牌的方案数,上边沿不能向上放,左边沿不能往左放以此类推,把这些减去,剩下方案的除以2 就是答案
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long sum[510][510][4];
char s[510][510];
int main()
{
    memset(s,0,sizeof(s));
    int h,w,l,t,r,b,q;
    long long ans=0,tot=0;
    scanf("%d%d ",&h,&w);
    for (int i=1;i<=h;i++)
    {
        for (int j=1;j<=w;j++)
            scanf("%c",&s[i][j]);
        scanf("\n");
    }
    for (int i=1;i<=h;i++)
        for (int j=1;j<=w;j++)
        {
            if (s[i][j]=='.'&&s[i-1][j]=='.') sum[i][j][0]=1;
            if (s[i][j]=='.'&&s[i][j-1]=='.') sum[i][j][1]=1;
            if (s[i][j]=='.'&&s[i+1][j]=='.') sum[i][j][2]=1;
            if (s[i][j]=='.'&&s[i][j+1]=='.') sum[i][j][3]=1;
            for (int k=0;k<=3;k++)
                sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+sum[i][j][k];
        }
    scanf("%d",&q);
    for (int i=1;i<=q;i++)
    {
        ans=0;
        scanf("%d%d%d%d",&t,&l,&b,&r);
        ans+=sum[t][r][0]-sum[t-1][r][0]-sum[t][l-1][0]+sum[t-1][l-1][0];
        ans+=sum[b][l][1]-sum[t-1][l][1]-sum[b][l-1][1]+sum[t-1][l-1][1];
        ans+=sum[b][r][2]-sum[b-1][r][2]-sum[b][l-1][2]+sum[b-1][l-1][2];
        ans+=sum[b][r][3]-sum[t-1][r][3]-sum[b][r-1][3]+sum[t-1][r-1][3];
        tot=0;
        for (int j=0;j<=3;j++)
            tot+=sum[b][r][j]-sum[t-1][r][j]-sum[b][l-1][j]+sum[t-1][l-1][j];
        tot=(tot-ans)/2;
        printf("%I64d\n",tot);
    }
    return 0;
}
D题问l-r之间有多少个形如k^n的数。。。直接暴力就好了,把unsigned long long 判一下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
unsigned long long l,r,k,tot=0;
const unsigned long long N=9223372036854775808ULL;
int main()
{
	scanf("%I64u%I64u%I64u",&l,&r,&k);
	for (unsigned long long tmp=1,tmp2;tmp<=r;tmp2=tmp,tmp*=k)
	{
		if (tmp2>(N/k))
			break;
		if (tmp>=l) 
		{
			if (tot!=0) printf(" ");
			printf("%I64u",tmp);
			tot++;
		}
	}
	if (tot==0) printf("-1");
	return 0;
} 
E题只要求多边形到多边形外一点的最远距离和最近距离就好,最远距离是顶点,最近距离可能是在边上,我判断的时候用叉积判断的,求距离也是用面积除以底算的,这样感觉比较稳,

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
double x[100100],y[100100],px,py;
double sqr(double x) {return x*x;}
double cj(double x1,double y1,double x2,double y2)
{
	return (x1-px)*(y2-py)-(x2-px)*(y1-py);
}
int main()
{
	double maxf=0;
	double minf=1000000000000;
	scanf("%d%lf%lf",&n,&px,&py);
	for (int i=1;i<=n+1;i++)
	{
		if (i<=n)
		{
			scanf("%lf%lf",&x[i],&y[i]);
			maxf=max(maxf,sqr(x[i]-px)+sqr(y[i]-py));
			minf=min(minf,sqr(x[i]-px)+sqr(y[i]-py));
		}
		else
		{
			x[i]=x[n];
			y[i]=y[n];
		}
		int tmp;
		if (i==1) continue;
		if (i>1&&i<=n) tmp=i-1;
		else tmp=1;
		if (fabs(x[i]-x[tmp])<1e-6) 
		{
			if (((py>y[i]&&py<y[tmp])||(py>y[tmp]&&py<y[i]))&&minf>sqr(x[i]-px))
				minf=sqr(x[i]-px);
		}
		else if (fabs(y[i]-y[tmp])<1e-6) 
		{
			if (((px>x[i]&&px<x[tmp])||(px>x[tmp]&&px<x[i]))&&minf>sqr(y[i]-py))
				minf=sqr(y[i]-py);
		}
		else 
		{
			double k=-(x[tmp]-x[i])/(y[tmp]-y[i]);
			double tmpx=px+1;
			double tmpy=py+k;
			if (cj(tmpx,tmpy,x[i],y[i])*cj(tmpx,tmpy,x[tmp],y[tmp])<0)
				minf=min(minf,sqr(fabs(cj(x[i],y[i],x[tmp],y[tmp])))/(sqr(x[tmp]-x[i])+sqr(y[tmp]-y[i])));
		}
	}
	printf("%.18f",(maxf-minf)*3.14159265358979323846264338);
	return 0;
}

F题是本次的防AK题,其实也什么难度。。只是比较绕,具体题解

传送门:http://blog.youkuaiyun.com/pro_space/article/details/50603622


祝大家训练愉快~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值