2016-9-17模拟题

T1  跑马圈地

Description

一觉醒来,小Hi穿越回了古代!由于破敌有功,大汗赏赐小Hi可以在敌人的草原上跑马圈地:一天之内骑马围住的草原以后就是小Hi的牧场。但是令小Hi头疼的是,敌人的草原上有一块臭水塘。小Hi不能骑马走进臭水塘里,并且即使小Hi的骑马路径围住了臭水塘,小Hi的牛马也不能在臭水塘里放牧。
为了更科学地圈地,小Hi对这个问题进行了简化和抽象:(1)敌人的草原是一块n×m的方格矩阵,(2)骑马的路径是沿着方格边缘的一段封闭折线,(3)臭水塘是矩阵中的一块矩形,(4)骑马的路径周长不超过L。小Hi想知道自己最大能圈住多大面积的草原(臭水塘的面积不计入在内)。

如图所示:图1是一条合法的路径;图2也是一条合法的路径,但是圈住的草原面积为0;图3不是合法的路径,因为没有封闭;图4也不是合法的路径,因为穿过了水塘。

Input

第一行3个整数:n, m, L;
第二行4个整数:l, r, t, b (0 ≤ l < r ≤ m, 0 ≤ t < b ≤ n)表示水塘的左、右、上、下边界坐标。

Output

小Hi最大能圈住的面积。

Sample Input

4 4 8
1 3 1 3

Sample Output

3

Hint

100%的数据:1 ≤ n, m ≤100, 1 ≤ L ≤ 400。
Analysis:
1.枚举在图中的所有点和围成矩形的一条边长,因为总长固定,所以可以O(1)求出另一条边。
但是需要分类讨论:(1)矩形的一个角在臭水塘里。(2)矩形的一边包住了臭水塘。(3)矩形包住了整个臭水塘。
最后还有一种情况:有可能矩形会向某个方向延伸一部分。期望的分:100分
2.臭水塘的四条边所在的直线将草原分成了9块,取周围的四块小矩形一一判断,有可能包住臭水塘的一部分,也有可能向矩形的长边延伸。期望的分:100分
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<memory.h>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
int n,m,L,l,r,t,b;
int ans=0;
inline void work(int x,int y){
int i,j,len=0,tmp=0;
if (x+y>=L/2){
  for (i=0;i<=x;i++)
  for (j=0;j<=y;j++)
  if (i+j<=L/2)
 ans=max(ans,i*j);
  return ;
}
if (r-l+x+b-t+y<=L/2){
  for (i=r-l+x;i<=m;i++)
  for (j=b-t+y;j<=n;j++)
  if (i+j<=L/2)tmp=max(tmp,i*j);
  tmp-=(r-l)*(b-t);
  ans=max(ans,tmp);
}
len=L-((x+y)<<1);
if (len/2<=m-x+n-y){
  tmp=x*y;
  if (x<y){
   if (m-x<=len/2)
    tmp+=y*(m-x)+((len-((m-x)*2))/2)*x;
   else tmp+=y*(len/2);
     //cout<<tmp<<endl;
       }
       else{
if (n-y<=len/2)
  tmp+=x*(n-y)+((len-((n-y)*2))/2)*y;
else tmp+=x*(len/1);
  }
    }
    ans=max(ans,tmp);
}
int main(){
    scanf("%d%d%d",&n,&m,&L);
    scanf("%d%d%d%d",&l,&r,&t,&b);
    work(l,n-b);
    work(l,t);
    work(m-r,t);
    work(m-r,n-b);
    //if(ans==4725)cout<<2475;
    //else  cout<<ans;
    cout<<ans;
    return 0;
}
T2: 自虐的小L

Description

五大学科竞赛之一的数学竞赛结束后,小L发现自己又被题目碾压了,心里非常不爽,于是暗下决心疯狂刷数学题,做到天昏地暗、废寝忘食(众人:这不是自虐吗……)有一天,他在做题时发现了一个有趣的问题:
给定n个二元组(ai,bi),记函数:
,函数y四舍五入取整。
将n个二元组去掉其中的k个计算一个新的y值,均能满足y≤λ: ,求出最小的λ 值。
自虐之余的小L还没有忘记和他朝夕相伴的OIer们,所以,他想让你们帮他一起找出 值 。

Input

输入包含多组数据,每组测试数据包含:
第一行两个数:N K;
第二行为N个数:a1 a2 … an
第三行为N个数:b1 b2 … bn
当N、K均为0时输入结束。

Output

对应每组数据输出一行,即找到的最小的 λ值。

Sample Input

3 1
5 0 1
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

Sample Output

83
100

Hint

为避免精度四舍五入出现误差,测试点保证每个函数值与最终结果的差值至少为0.001,你可以理解为,不会出现函数值为83.4997。
40%的数据:N≤20;
70%的数据:N≤1000;
100%的数据:N≤10000。
Analysis:
sum(ai)/sum(bi)>=x   ==>   sum(ai)>=sum(x*bi)   ==>  sum(ai-x*bi)>=0    记ci=ai-x*bi,按ci排序,只需二分x即可
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<memory.h>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=10005;
int N,K;
ll a[maxn],b[maxn];
ll c[maxn];
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
bool check(ll x){
int i;
ll sum=0;
for(i=1;i<=N;i++){c[i]=a[i]*1000-x*b[i];sum+=c[i];}
sort(c+1,c+1+N);
for(i=1;i<=K;i++)sum-=c[i];
return sum>=0;
}
inline void Binary_Search(){
ll left=0,right=100000,mid=(left+right)/2,ans=0;
int tot=0;
while(left<=right){
mid=(left+right)/2;
if(check(mid)){
if(mid>ans)ans=mid;
left=mid+1;
}
else right=mid-1;
}
printf("%lld\n",(ll)((double)ans/10.0+0.5));
}
int main(){
while(1){
N=read();K=read();
if(N==0&&K==0)break;
for(int i=1;i<=N;i++)a[i]=read();
for(int i=1;i<=N;i++)b[i]=read();
Binary_Search();
}
return 0;
T3: 生日礼物

Description

马上就是小新的生日了,小L打算给小新买生日礼物。
在买礼物的商店,所有的商品被排成了一行,每个商品小新都有一个喜爱程度Wi。小L希望买下连续的一段或两段礼物使得小新的喜爱程度之和最大(众人:买礼物居然一段一段的买,土豪啊……)。
可是,小L不知道到底是送小新连续的一段礼物还是两段礼物,于是,他想了一个机智的办法:假设一段礼物的喜爱程度和为S1,两段礼物的喜爱程度和为S2,假如S2-S1是质数,小L就买一段的礼物,否则,就买两段的礼物。(小L:哈哈,我机智吧! 众人:你NC!)。

Input

第一行为一个整数N,表示礼物总数;
第二行N个整数,W1,W2…Wn,表示小新对每个礼物的喜爱程度。

Output

一个整数,表示小L买给小新的礼物的喜爱程度之和。

Sample Input

5
-5 9 -5 11 20

Sample Output

35

Hint

30%的数据:N≤1000;
60%的数据:N≤10000;
100%的数据:N≤1000000。
提示:
Analysis:
1.直接暴力(虽然我没写对),期望得分:30分
2.其实这题是三题中最简单的,只要预处理出所有以i为结尾和以i为开头的最大字段和就行了,最后从头到尾扫一遍,不断更新s2,再判一下质数即可
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<memory.h>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000050;
int N;
ll f1[maxn],f2[maxn];
int a[maxn];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline bool isprime(ll x){
if(x<=1)return false;
for(ll i=2;i*i<=x;i++)
if(x%i==0)return false;
return true;
}
int main(){
int i;N=read();
ll tmp=0;
ll s1=0,s2=-(1<<30);
for(i=1;i<=N;i++){
a[i]=read();
if(tmp+a[i]>0)tmp+=a[i];
else tmp=0;
f1[i]=max(f1[i-1],tmp);
}
s1=f1[N];
tmp=0;
for(i=N;i>=1;i--){
if(tmp+a[i]>0)tmp+=a[i];
else tmp=0;
f2[i]=max(f2[i+1],tmp);
}
for(i=1;i<N;i++)s2=max(s2,f1[i]+f2[i+1]);
if(isprime(s2-s1))cout<<s1;
else cout<<s2;
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值