2017-10-2 清北刷题冲刺班p.m
最大值
(max)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK有一本书,上面有很多有趣的OI问题。今天LYK看到了这么一道题目:
这里有一个长度为n的正整数数列ai(下标为1~n)。并且有一个参数k。
你需要找两个正整数x,y,使得x+k<=y,并且y+k-1<=n。并且要求a[x]+a[x+1]+…+a[x+k-1]+a[y]+a[y+1]+…+a[y+k-1]最大。
LYK并不会做,于是它把题扔给了你。
输入格式(max.in)
第一行两个数n,k。
第二行n个数,表示ai。
输出格式(max.out)
两个数表示x,y。若有很多种满足要求的答案,输出x最小的值,若x最小仍然还有很多种满足要求的答案,输出y最小的值。
输入样例
5 2
6 1 1 6 2
输出样例
1 4
对于30%的数据n<=100。
对于60%的数据n<=1000
对于100%的数据1<=n<=100000,1<=k<=n/2,1<=ai<=10^9。
/*
题目就是让求长度为k的两个互不重叠区间的和最大
枚举两个区间的开头,用前缀和求一下
*/
#include<iostream>
#include<cstdio>
#define maxn 100010
using namespace std;
int n,k,a[maxn],x,y;
long long sum[maxn],mx;
int main(){
//freopen("Cola.txt","r",stdin);
freopen("max.in","r",stdin);freopen("max.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
}
long long sum1,sum2;
for(int s1=;s1<=n-*k+;s1++){
sum1=sum[s1+k-]-sum[s1-];
for(int s2=s1+k;s2<=n-k+;s2++){
sum2=sum[s2+k-]-sum[s2-];
if(sum1+sum2>mx){
mx=sum1+sum2;
x=s1,y=s2;
}
}
}
printf("%d %d",x,y);
fclose(stdin);fclose(stdout);
return ;
}
60分 暴力
/*
b[i]表示左端点在i长度为k的区间这个和是多少
找一个x,找一个y,使得x+k<=y,并且y+k-1<=n 并且b[x]+b[y]最大 当固定x的时候, x+k<=y<=n-k+1 区间求最大 -> 线段树/倍增表 nlgn
当x从大变小的时候, y解锁了一个位置 拿这个数来更新b[y]的最大值 O(n)
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,a[],i,ansx,ansy;
long long sum[],MAX,MAX1[],MAX2[],x2[],x1[];
int main()
{
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
scanf("%d%d",&n,&m);
for (i=; i<=n; i++) scanf("%d",&a[i]);
for (i=; i<=n; i++)
sum[i]=sum[i-]+(long long)a[i];
// return 0;
for (i=m; i<=n; i++)
{
//if (i%1000==0)cout<<i<<endl;
if (MAX1[i-]>=sum[i]-sum[i-m])
{
x1[i]=x1[i-];
MAX1[i]=MAX1[i-];
}
else
{
x1[i]=i-m+;
MAX1[i]=sum[i]-sum[i-m];
}
}
for (i=n-m+; i>=; i--)
{
if (MAX2[i+]>sum[i+m-]-sum[i-])
{
x2[i]=x2[i+];
MAX2[i]=MAX2[i+];
}
else
{
x2[i]=i;
MAX2[i]=sum[i+m-]-sum[i-];
}
}
for (i=m; i<=n-m; i++)
{
if (MAX1[i]+MAX2[i+]>MAX)
{
MAX=MAX1[i]+MAX2[i+];
ansx=x1[i]; ansy=x2[i+];
}
}
printf("%d %d\n",ansx,ansy);
return ;
}
100分 前缀和+线段树/倍增表
吃东西
(eat)
Time Limit:2000ms Memory Limit:1024MB
题目描述
一个神秘的村庄里有4家美食店。这四家店分别有A,B,C,D种不同的美食。LYK想在每一家店都吃其中一种美食。每种美食需要吃的时间可能是不一样的。
现在给定第1家店A种不同的美食所需要吃的时间a1,a2,…,aA。
给定第2家店B种不同的美食所需要吃的时间b1,b2,…,bB。
以及c和d。
LYK拥有n个时间,问它有几种吃的方案。
输入格式(eat.in)
第一行5个数分别表示n,A,B,C,D。
第二行A个数分别表示ai。
第三行B个数分别表示bi。
第四行C个数分别表示ci。
第五行D个数分别表示di。
输出格式(eat.out)
一个数表示答案。
输入样例
11 3 1 1 1
4 5 6
3
2
1
输出样例
2
对于30%的数据A,B,C,D<=50
对于另外30%的数据n<=1000。
对于100%的数据1<=n<=100000000,1<=A,B,C,D<=5000,0<=ai,bi,ci,di<=100000000。
#include<iostream>
#include<cstdio>
#include<ctime>
#include<algorithm>
#define maxn 5010
using namespace std;
int n,A,B,C,D,a[maxn],b[maxn],c[maxn],d[maxn],cnt;
long long v[],ans;
int find(int x){
int l=,r=cnt,res=;
while(l<=r){
int mid=(l+r)>>;
if(v[mid]<=x)res=mid,l=mid+;
else r=mid-;
}
return res;
}
int main(){
//freopen("data.txt","r",stdin);
freopen("eat.in","r",stdin);freopen("eat.out","w",stdout);
scanf("%d%d%d%d%d",&n,&A,&B,&C,&D);
for(int i=;i<=A;i++)scanf("%d",&a[i]);
for(int i=;i<=B;i++)scanf("%d",&b[i]);
for(int i=;i<=C;i++)scanf("%d",&c[i]);
for(int i=;i<=D;i++)scanf("%d",&d[i]);
sort(a+,a+A+);sort(b+,b+B+);
sort(c+,c+C+);sort(d+,d+D+);
if(a[A]+b[B]+c[C]+d[D]<=n){
ans=1LL*A*B*C*D;
cout<<ans;
return ;
}
for(int i=;i<=A;i++){
if(a[i]>n)break;
for(int j=;j<=B;j++){
if(a[i]+b[j]>n)break;
v[++cnt]=a[i]+b[j];
}
}
sort(v+,v+cnt+);
for(int i=;i<=C;i++){
if(c[i]>n)break;
for(int j=;j<=D;j++){
if(c[i]+d[j]>n)break;
int pos=find(n-c[i]-d[j]);//小于等于某数的最后一个位置
ans+=pos;
}
}
cout<<ans;
fclose(stdin);fclose(stdout);
return ;
}
70分 折半枚举
/*
1024MB*1024*1024/4 = 225000000个int数组
A和B C和D
A和B和C和D A和B中的一种 C和D的一种
A和B 双重循环 来得到一个f[i]表示花了i这个时间有几种可能 A*B
进行桶排序,把f按次序的放进x数组中,A*B种可能排个序
C和D 双重循环 来得到一个g[i]表示花了i这个时间有几种可能 C*D
进行桶排序,把g按次序的放进y数组中,C*D种可能排个序
A*B 一个数组x C*D的一个数组y 查询存在多少对i,j,使得x[i]+y[j]<=n (x和y都是有序的)
x和y都是顺序的。 x[1] y[?] 一个前缀(1~p)
x[2] y[??] 一个前缀(1~pp) pp<=p
x[3] y[???] 一个前缀(1~ppp) ppp<=pp 当一个规模解决不了的时候,分成两半 meet in the middle */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int f[],c[],cc[];
int A,B,C,D,n,a[],b[],aa[],bb[],MAX,cnt,cntt,i,j,now;
long long ans;
int main()
{
freopen("eat.in","r",stdin);
freopen("eat.out","w",stdout);
scanf("%d%d%d%d%d",&n,&A,&B,&C,&D);
if (n== && A== && B== && C== && D==) return ;
for (i=; i<=A; i++) scanf("%d",&a[i]);
for (i=; i<=B; i++) scanf("%d",&b[i]);
MAX=;
cnt=cntt=;
for (i=; i<=A; i++)
for (j=; j<=B; j++)
if (a[i]+b[j]<=n)
{
f[a[i]+b[j]]++;
MAX=max(MAX,a[i]+b[j]);
}
for (i=; i<=MAX; i++)
while (f[i])
{
f[i]--;
c[++cnt]=i;
} for (i=; i<=C; i++) scanf("%d",&aa[i]);
for (i=; i<=D; i++) scanf("%d",&bb[i]);
MAX=;
for (i=; i<=C; i++)
for (j=; j<=D; j++)
if (aa[i]+bb[j]<=n)
{
f[aa[i]+bb[j]]++;
MAX=max(MAX,aa[i]+bb[j]);
}
for (i=; i<=MAX; i++)
while (f[i])
{
f[i]--;
cc[++cntt]=i;
}
for (i=cntt; i>=; i--) if (c[]+cc[i]<=n) break;
now=i;
for (i=; i<=cnt; i++)
{
ans+=now;
while (now&& c[i+]+cc[now]>n) now--;
}
cout<<ans<<endl;
ans=;
return ;
}
100分 meet in the middle
分糖果
(candy)
Time Limit:1000ms Memory Limit:128MB
题目描述
总共有n颗糖果,有3个小朋友分别叫做L,Y,K。每个小朋友想拿到至少k颗糖果,但这三个小朋友有一个共同的特点:对3反感。也就是说,如果某个小朋友拿到3颗,13颗,31颗,333颗这样数量的糖果,他就会不开心。(也即它拿到的糖果数量不包含有一位是3)
LYK掌管着这n颗糖果,它想问你有多少种合理的分配方案使得将这n颗糖果全部分给小朋友且没有小朋友不开心。
例如当n=3,k=1时只有1种分配方案,当n=4,k=1时有3种分配方案分别是112,121,211。当n=7,k=2时则不存在任何一种合法的方案。
当然这个答案可能会很大,你只需输出答案对12345647取模后的结果就可以了。
输入格式(candy.in)
第一行两个数表示n,k。
输出格式(candy.out)
一个数表示方案总数。
输入样例
99999 1
输出样例
9521331
对于30%的数据n<=100
对于50%的数据n<=1000。
对于另外30%的数据k=1。
对于100%的数据3<=n<=10^10000,1<=k<=n/3,且n,k不包含前导0。
#include<iostream>
#include<cstdio>
#define mod 12345647
using namespace std;
int n,k,ans;
bool check(int x){
while(x){
if(x%==)return ;
x/=;
}
return ;
}
int main(){
freopen("candy.in","r",stdin);freopen("candy.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=k;i<=n-k-k;i++){
for(int j=k;i+j<=n-k;j++){
int k=n-i-j;
if(check(i)&&check(j)&&check(k))ans++;
if(ans>=mod)ans-=mod;
}
}
cout<<ans;
fclose(stdin);fclose(stdout);
return ;
}
50分 暴力
/*
枚举两个数,第三个数是确定,判断一下。 f[i]表示i这个数字是否有3 dp[i][j][0/1][0/1][0/1]来表示当前从高到低第i位,并且这一位需要向它的高位进j位 j=[0,2] 这3个数分别是否超过了k for (i=1; i<=|a|; i++)
for (j=0; j<=2; j++)
for (u=0; u<=1; u++)
for (v=0; v<=1; v++)
for (w=0; w<=1; w++)
for (x=0; x<=9; x++)
for (y=0; y<=9; y++)
for (z=0; z<=9; z++)
if (x+y+z>=10*j && x!=3 && y!=3 && z!=3)
{
int k=x+y+z-10*j;
if (k==a[i]) {dp[i+1][0][][][]+=dp[i][j];}
if (k==a[i]-1) {dp[i+1][1][][][]+=dp[i][j];}
if (k==a[i]-2) {dp[i+1][2][][][]+=dp[i][j];}
}
n=|a|
cout<<dp[n][0];
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
const int MOD=;
int dp[][][][][],a[],b[],len1,len2,i,j,k,l,t,I,J,K,L,T,s1,s2,s3,ans;
char n[],LL[];
void ADD(int &A,int B) {A+=B; if (A>=MOD) A-=MOD;}
int main()
{
freopen("candy.in","r",stdin);
freopen("candy.out","w",stdout);
scanf("%s",n);
scanf("%s",LL);
len1=strlen(n); len2=strlen(LL);
for (i=; i<len1; i++) a[i+]=n[i]-'';
for (i=; i<len1; i++) b[i+]=;
for (i=; i<len2; i++) b[+i+len1-len2]=LL[i]-'';
for (i=; i<=len1; i++)
for (j=; j<=; j++)
for (k=; k<=; k++)
for (l=; l<=; l++)
for (t=; t<=; t++) dp[i][j][k][l][t]=;
dp[][][][][]=;
for (i=; i<len1; i++)
for (j=; j<=; j++)
for (k=; k<=; k++)
for (l=; l<=; l++)
for (t=; t<=; t++)
if (dp[i][j][k][l][t])
{
for (s1=; s1<=; s1++)
if (s1!=)
for (s2=; s2<=; s2++)
if (s2!=)
for (s3=; s3<=; s3++)
if (s3!=)
{
I=i+;
J=j*+a[i+]-s1-s2-s3;
if (J> || J<) continue;
if (k== && s1<b[i+]) continue;
K=(k || s1>b[i+]);
if (l== && s2<b[i+]) continue;
L=(l || s2>b[i+]);
if (t== && s3<b[i+]) continue;
T=(t || s3>b[i+]);
ADD(dp[I][J][K][L][T],dp[i][j][k][l][t]);
}
}
for (k=; k<=; k++) for (l=; l<=; l++) for (t=; t<=; t++) ADD(ans,dp[len1][][k][l][t]);
cout<<ans<<endl; ans=;
return ;
}
100分 数位dp
2017-10-2 清北刷题冲刺班p.m的更多相关文章
- 2017-10-4 清北刷题冲刺班p.m
P102zhx a [问题描述]你是能看到第一题的 friends 呢.——hja两种操作:1.加入一个数.2.询问有多少个数是?的倍数.[输入格式]第一行一个整数?,代表操作数量.接下来?行,每行两 ...
- 2017-10-4 清北刷题冲刺班a.m
P101zhx a [问题描述]你是能看到第一题的 friends 呢.——hjaHja 拥有一套时光穿梭技术,能把字符串以超越光速的速度传播,但是唯一的问题是可能会 GG.在传输的过程中,可能有四种 ...
- 2017-10-3 清北刷题冲刺班p.m
a [问题描述]你是能看到第一题的 friends 呢.——hja给你一个只有小括号和中括号和大括号的括号序列,问该序列是否合法.[输入格式]一行一个括号序列.[输出格式]如果合法,输出 OK,否则输 ...
- 2017-10-3 清北刷题冲刺班a.m
P99zhx a [问题描述]你是能看到第一题的 friends 呢.——hja怎么快速记单词呢?也许把单词分类再记单词是个不错的选择.何大爷给出了一种分单词的方法,何大爷认为两个单词是同一类的当这两 ...
- 2017-10-2 清北刷题冲刺班a.m
一道图论神题 (god) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只 ...
- 2017-10-1 清北刷题冲刺班p.m
一道图论好题 (graph) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图 ...
- 2017-10-7 清北刷题冲刺班p.m
测试 A 同花顺 文件名 输入文件 输出文件 时间限制 空间限制card.cpp/c/pas card.in card.out 1s 512MB题目描述所谓同花顺,就是指一些扑克牌,它们花色相同,并且 ...
- 2017-10-7 清北刷题冲刺班a.m
测试 A 消失的数字 文件名 输入文件 输出文件 时间限制 空间限制del.cpp/c/pas del.in del.out 1s 512MB题目描述现在,我的手上有 n 个数字,分别是 a 1 ,a ...
- 2017-10-1 清北刷题冲刺班a.m
位运算1 (bit) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK拥有一个十进制的数N.它赋予了N一个新的意义:将N每一位都拆开来后再加起来就是N所拥 ...
随机推荐
- Unity3D之Mesh(三)绘制四边形
前言: 由於之前的基本介紹,所以有關的知識點不做贅述,只上案例,知識作爲自己做試驗的記錄,便於日後查看. 步驟: 1.創建一個empty 的gameobject: 2.添加一個脚本給這個game ob ...
- Opencv - Android 配置安装
1.道具们: windows 7 64位 OpenCV-2.4.6-android-sdk-r2 ( http://sourceforge.net/projects/opencvlibrary/fil ...
- 树套树Day2
滚回来更新,,, 在Day1我们学了最基本的线段树套平衡树 Day2开始我们要学习一些黑科技 (所以很大概率会出现Day3 w 1.线段树上的黑科技 这一段我们分几项来讲 1.权值线段树 权值线段树以 ...
- webpack打包APP的后端地址处理
PC端我们用webpack打包,只需要写相对路径,发布的时候和后端接口在同一目录下即可. 但是做过APP或者混合开发的同学都知道,APP不需要发布的,如果后端地址还是用相对路径的话,可想而知,调用后端 ...
- 制作spark镜像
构建镜像 添加jdk引用(可以使用yum进行安装): 安装SSH 碰到一个问题,执行systemctl的时候发生了异常: Failed to get D-Bus connection 解决这个问题的方 ...
- Android HttpGet和HttpPost设置超时
HttpPost: private Runnable runnable = new Runnable() { @Override public void run() { String url = Ba ...
- 【转】Pro Android学习笔记(十七):用户界面和控制(5):日期和时间控件
目录(?)[-] DatePicker和TimePicker控件 DigitalClock和AnalogClock控件 DatePicker和TimePicker控件 使用DatePicker和Tim ...
- Java类的生命周期(转)
引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告 ...
- oracle--视图(2)---
Oracle---视图 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以对表里面的数据进行查询和修改.视图基于的表称为基表,Oracle的数据库对象分为五种:表,视图,序列,索引和同 ...
- Python-Redis的Hash操作
Redis的hash是一个string类型的field和value的映射表,特别适合用于存储对象,每个hash可以存储40多亿键值对 hset(name, key, value):创建一个name的类 ...