您的位置:首页 > 其它

【题解】BUPT 2015 freshman contest 2

2016-02-04 00:56 357 查看
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
;
y[i]=y
;
}
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.csdn.net/pro_space/article/details/50603622

祝大家训练愉快~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: