Problem1 单峰

小X 归来后,首先对数列很感兴趣。他想起有1类特殊的数列叫单峰数列。 我们说一个数列 {ai} 是单峰的,当且仅当存在一个位置 k 使得 ai < ai+1(i < k) 且 ai > ai+1(i ≥ k)。 现在小X 想知道,对于 1 到 n 的所有排列,其中有多少个是单峰数列。 Input 第1行包含1个整数 n。 Output 第一行包含一个整数,表示答案除以 1e9 + 7 的余数。 Example

unimodal.in unimodal.out
2 2

Scoring • 对于 20% 的数据, n ≤ 10。 • 对于 50% 的数据, n ≤ 105。 • 对于 100% 的数据, 2 ≤ n ≤ 1018。

解析:

1.1 20 分做法

生成所有全排列并判断,时间复杂度 O(n · n!)。
1.2 50 分做法
根据排列组合可以发现,峰顶一定是 n,因此考虑 1 ∼ n - 1 分别放在 n 的左边还是右边,一一得出相应
的唯一方案。所以答案就是 2^(n-1),时间复杂度 O(n)。
1.3 100 分做法
 对2^(n-1)用快速幂即可,时间复杂度 O(log n)。

代码:

#include<bits/stdc++.h>
using namespace std;
template <class T>
inline void readl(T &x)
{ x=0;bool f=0;char ch=getchar();
while(!isdigit(ch)) { f=(ch==45);ch=getchar();}
while( isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?(~x+1):x;}
long long n;
const int md=1e9+7;
inline long long bpow(long long a,long long b)
{ long long base=a;
long long ans=1;
while(b)
{
if(b&1) ans=(ans%md*base%md)%md;
base=base*base%md;
b>>=1;
}
return ans%md;
}
int main()
{ freopen("unimodal.in","r",stdin);
freopen("unimodal.out","w",stdout);
readl(n);
printf("%lld\n",(bpow(2,n-1)%md));
return 0;
}

Problem2 积木

小X 感到很无聊,从柜子里翻出了他小时候玩的积木, 这套积木共有 n 块,每块积木都是1个长方体。小X 想用这些积木拼成1个积木塔(不必每块 积木都使用, 所谓积木塔,就是将积木1个1个摞起来,(除去最底层的积木外)每块积木的底下必须能被它下面 的积木的底面完全包含(即对应的长宽都要更小或相等)。当然,积木可以任意放置,即可以以任意一面 作为底面。 现在小X 想知道,积木塔最大能拼多高。 Input 第⼀⾏包含⼀个整数 n。 接下来 n ⾏,每⾏包含三个整数 a; b; c,表⽰该块积木是⼀个 a × b × c 的长⽅体。 Output 第⼀⾏包含⼀个整数,表⽰答案。 Example

brick.in brick.out

3

8 7 6

3 9 4

1 10 5

18

Explanation 选择第 1 块积木和第 3 块积木。

Scoring   • 对于 10% 的数据, n = 1。

    • 对于 40% 的数据, n ≤ 6。

    • 对于 100% 的数据, 1 ≤ n ≤ 15, 1 ≤ a; b; c ≤ 108。

解析:

2.1 10 分做法
输出 maxfa; b; cg。
2.2 40 分做法
生成全排列,然后枚举每个积木哪个面朝上,时间复杂度 O(n! · 3n)。
2.3 100 分做法
显然是状态压缩 DP。设计状态 f[S][i][0/1/2] 表示已经用了集合 S 内的积木,最顶上是编
号为 i 的积木,它的哪个面朝上。转移时枚举不在 S 内的积木,以及朝上的面判断即可。时间
复杂度 O(2n · (3n)2)。

PS:但是这道题的数据有点弱,只要搜索写得好,照样可以过。

代码:

1.DP

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int readl()
{
int x=0,fg=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')fg=-fg;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*fg;
}
int n,a[200],b[200],c[200],t[20],mx=-100,bin[200];
ll ans=-100;
ll f[(1<<15)+10][16][3];
int main()
{
freopen("brick.in","r",stdin);
freopen("brick.out","w",stdout);
n=readl();
for(int i=1;i<=n;i++)
{
a[i]=readl();b[i]=readl();c[i]=readl();
t[1]=a[i];t[2]=b[i];t[3]=c[i];
sort(t+1,t+4);
a[i]=t[1];b[i]=t[2];c[i]=t[3];
mx=max(mx,t[3]);
}
if(n==1){printf("%d",mx);return 0;}
bin[1]=1;
for(int i=2;i<=20;i++)bin[i]=bin[i-1]*2;
for(int i=1;i<=n;i++)
{
f[bin[i]][i][0]=a[i];
f[bin[i]][i][1]=b[i];
f[bin[i]][i][2]=c[i];
}
//printf("%lld %lld %lld\n",f[1][1][0],f[1][1][1],f[1][1][2]);
for(int x=0;x<(1<<n);x++)
for(int i=1;i<=n;i++)
{ if(x&bin[i])continue;
for(int j=1;j<=n;j++)
{
if((x&bin[j])==0)continue;
int s=x|bin[i];
if(b[j]>=b[i]&&c[j]>=c[i])f[s][i][0]=max(f[x][j][0]+a[i],f[s][i][0]);
if(c[j]>=c[i]&&a[j]>=b[i])f[s][i][0]=max(f[s][i][0],f[x][j][1]+a[i]);
if(b[j]>=c[i]&&a[j]>=b[i])f[s][i][0]=max(f[s][i][0],f[x][j][2]+a[i]); if(c[j]>=c[i]&&b[j]>=a[i])f[s][i][1]=max(f[s][i][1],f[x][j][0]+b[i]);
if(c[j]>=c[i]&&a[j]>=a[i])f[s][i][1]=max(f[s][i][1],f[x][j][1]+b[i]);
if(b[j]>=c[i]&&a[j]>=a[i])f[s][i][1]=max(f[s][i][1],f[x][j][2]+b[i]); if(c[j]>=b[i]&&b[j]>=a[i])f[s][i][2]=max(f[s][i][2],f[x][j][0]+c[i]);
if(c[j]>=b[i]&&a[j]>=a[i])f[s][i][2]=max(f[s][i][2],f[x][j][1]+c[i]);
if(b[j]>=b[i]&&a[j]>=a[i])f[s][i][2]=max(f[s][i][2],f[x][j][2]+c[i]);
ans=max(ans,max(f[s][i][0],max(f[s][i][1],f[s][i][2])));
//printf("%d %d %d %d ***\n",x,s,i,j);
//printf("%lld %lld %lld\n",f[s][i][0],f[s][i][1],f[s][i][2]);
}
}
printf("%lld",ans);
fclose(stdin);fclose(stdout);
return 0;
}

2.DFS

#include<bits/stdc++.h>
using namespace std;
template <class T>
inline void readl(T &x)
{ x=0;bool f=0;char ch=getchar();
while(!isdigit(ch)) { f=(ch==45);ch=getchar();}
while( isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?(~x+1):x;} int n,maxn=0;
bool vis[1001];
struct node
{ int mx,h[4],x[4],y[4];}e[100];
void dfs(int H,int x,int y)
{ maxn=max(maxn,H);
for(register int i=n;i>=1;i--)
if(!vis[i])
{ vis[i]=1;
for(register int j=1;j<=3;j++)
if(e[i].x[j]<=x&&e[i].y[j]<=y)
dfs(H+e[i].h[j],e[i].x[j],e[i].y[j]);
vis[i]=0;
}
}
int main()
{ freopen("brick.in","r",stdin);
freopen("brick.out","w",stdout);
readl(n);
for(register int i=1,x,y,z;i<=n;i++)
{ readl(x);readl(y);readl(z);
e[i].mx=max(x,max(y,z));
e[i].x[1]=min(x,y);e[i].y[1]=max(x,y);e[i].h[1]=z;
e[i].x[2]=min(y,z);e[i].y[2]=max(y,z);e[i].h[2]=x;
e[i].x[3]=min(x,z);e[i].y[3]=max(x,z);e[i].h[3]=y;
}
if(n==1){printf("%d",e[1].mx);return 0;}
for(int i=1;i<=n;i++)
{ vis[i]=1;
for(int j=1;j<=3;j++)
dfs(e[i].h[j],e[i].x[j],e[i].y[j]);
vis[i]=0;
}
printf("%d",maxn);
return 0;
}

Problem3 同余

小X 望着草稿纸上的数列,结合自己对同余的粗浅认识,又想到了个新问题。 对于1个长度为 n 的数列 {ai},每次询问将给出1组数 l; r; p; q,小X 想知道有多少个 i 满足 l ≤ i ≤ r 且 ai ≡ q (mod p)。 小X 沉迷这个问题,因此一共进行了 m 次询问。 Input 第⼀⾏包含两个整数 n; m。 第⼆⾏包含 n 个整数,表⽰数列 faig。 接下来 m ⾏,每⾏包含四个整数 l; r; p; q,表⽰⼀次询问。 Output m ⾏,每⾏包含⼀个整数,表⽰该次询问的答案。 Example

congruence.in congruence.out

5 2

1 5 2 3 7

1 3 2 1

2 5 3 0

2

1

Scoring   • 对于 20% 的数据, ai ≤ 1。

     • 对于 60% 的数据, ai ≤ 100。

     • 对于 100% 的数据, 1 ≤ m ≤ 105, 1 ≤ l ≤ r ≤ n ≤ 105, 0 ≤ q < p ≤ 10000, 0 ≤ ai ≤ 10000。

解析:

3.1 20 分做法
ai 6 1,因此转变为求区间内 0 和 1 的个数,用前缀和优化,注意 p = 1 的情况。时间复杂
度 O(n + m)。
3.2 60 分做法
同上面,用至多 101 个前缀和即可,时间复杂度 O(ai(n + m))。
3.3 100 分做法
观察到,其实要求的是某一范围内 kp + q 的个数,当 p 较大时, k 的取值范围很小。不妨
设“较大”的界限是 > K。
考虑将问题拆开来并排序,这样每个问题就变成了询问 1 ∼ r 中有多少个 kp + q。维护⼀
个哈希数组, h[i] 表示 i 有多少个;以及⼀个模数数组 g[i][j],表示模 i 为 j 有多少个。
每次指针向右移,直到移动到当前询问的位置,每移一次就将这个数分别在两个数组内标
记,复杂度总体是 O (nK)。
每次询问时,对于较小的 p 直接在 g 中查询,对于较⼤的 p 枚举 k 并在 h 中查询。
可以看出 K = √ai = 100 时最优。

代码:

1.100分

#include<bits/stdc++.h>
using namespace std;
template <class T>
inline void readl(T &x)
{ x=0;bool f=0;char ch=getchar();
while(!isdigit(ch)) { f=(ch==45);ch=getchar();}
while( isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?(~x+1):x;}//读入优化 int n,m;
int a[100100],sum[100100],ans[100100];
struct range
{ int r,id,p,q,opt;}e[100100<<1];//注意开两倍的空间
int maxn=0;
int cmp(range a,range b)
{ return a.r<b.r;}
int main()
{ freopen("congruence.in","r",stdin);
freopen("congruence.out","w",stdout);
readl(n);readl(m);
for(int i=1;i<=n;i++)
readl(a[i]);
for(int i=1,l,r,p,q;i<=m;i++)
{ readl(l);readl(r);readl(p);readl(q);
e[i].r=l-1; e[i].id=i; e[i].p=p; e[i].q=q; e[i].opt=-1;//需要计算sum[r]-sum[l-1]
e[i+m].r=r;e[i+m].id=i;e[i+m].p=p;e[i+m].q=q;e[i+m].opt=1;//将左右两边分开计算,将无序的提问变为线性的区间计算
}
sort(e+1,e+1+2*m,cmp);
int tail=0;//解析中的指针
for(int i=1;i<=2*m;i++)
{ while(tail<e[i].r)
{ tail++;
sum[a[tail]]++;//将所有的数字出现的个数都统计一遍
maxn=max(maxn,a[tail]);//统计最大值,方便确定下文kp+q的界限
}
for(int j=0;j*e[i].p+e[i].q<=maxn;j++)//解析中的kp+q
ans[e[i].id]+=sum[j*e[i].p+e[i].q]*e[i].opt;//e[i].id表示询问的序号,如果opt=-1就代表左界限,乘积为负代表减去[1,l-1]的值,opt=1同理
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);//输出答案
return 0;
}

2.60分(重点是理解40%的前缀和写法)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int readl()
{
int x=0,fg=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')fg=-fg;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*fg;
}
int n,m,a[101000],s[101000],v[100010][101];
int ac[101000];
int calc(int l,int r,int p,int q)
{
int ret=0;
for(int i=l;i<=r;i++)
if(a[i]%p==q%p)ret++;
return ret;
}
int main()
{
freopen("congruence.in","r",stdin);
freopen("congruence.out","w",stdout);
n=readl();m=readl();
int bo=0;
for(int i=1;i<=n;i++)
{
a[i]=readl();if(a[i]>1)bo=1;
}
int ans,l,r,p,q;
if(n<=5010&&m<=5010)
{
for(int i=1;i<=m;i++)
{
l=readl();r=readl();p=readl();q=readl();
printf("%d\n",calc(l,r,p,q));
}
return 0;
}
if(bo==0)
{
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
for(int i=1;i<=m;i++)
{
l=readl();r=readl();p=readl();q=readl();
if(p==1){ans=r-l+1;printf("%d\n",ans);continue;}
if(q%p==0)ans=r-l+1-s[r]+s[l-1];
if(q%p==1)ans=s[r]-s[l-1];
if(q%p>1)ans=0;
printf("%d\n",ans);
}
return 0;
}
for(int i=1;i<=n;i++)//重点
for(int j=0;j<=100;j++)
{
v[i][j]=v[i-1][j];
if(a[i]==j)v[i][j]++;
}
for(int i=1;i<=m;i++)
{
l=readl();r=readl();p=readl();q=readl();ans=0;
if(p==1){ans=r-l+1;printf("%d\n",ans);continue;}
ac[0]=0;
for(int i=0;i<=100;i++)
if(i%p==q%p)ac[++ac[0]]=i;
for(int i=1;i<=ac[0];i++)
ans=ans+v[r][ac[i]]-v[l-1][ac[i]];
printf("%d\n",ans);
}
fclose(stdin);fclose(stdout);
return 0;
}

  

小X归来 模拟赛1 解析的更多相关文章

  1. CONTEST36 小Z的模拟赛(2)

    A.小Z的可恶路障 题目:http://www.luogu.org/problem/show?pid=U126 题解:暴力也可以过吧.我为了保险先求了一次最短路,然后枚举这条最短路上的所有边... 代 ...

  2. 小奇模拟赛9.13 by hzwer

    2015年9月13日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...

  3. 【20170521校内模拟赛】热爱生活的小Z

    学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的. 所有试题如无特殊声明,开启-O2优化,时限 ...

  4. Java 第十一届 蓝桥杯 省模拟赛 小明的城堡

    小明用积木搭了一个城堡. 为了方便,小明在搭的时候用的是一样大小的正方体积本,搭在了一个 n 行 m 列的方格图上,每个积木正好占据方格图的一个小方格. 当然,小明的城堡并不是平面的,而是立体的.小明 ...

  5. Java 第十一届 蓝桥杯 省模拟赛 小明植树(DFS)

    小明植树 题目 问题描述 小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗. 小明和朋友们一共有 n 个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n ...

  6. [GRYZ]寒假模拟赛

    写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...

  7. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  8. NOIP第7场模拟赛题解

    NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...

  9. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

随机推荐

  1. 0_Simple__simpleMultiCopy

    利用 CUDA 的 Overlap 特性同时进行运算和数据拷贝来实现加速. ▶ 源代码.使用 4 个流一共执行 10 次 “数据上传 - 内核计算 - 数据下载” 过程,记录使用时间. #includ ...

  2. Amazon AWS S3 操作手册

    Install the SDK The recommended way to use the AWS SDK for Java in your project is to consume it fro ...

  3. Spring boot profile 多环境配置

    1.多Profile文件 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml 默认使用application.properties的配置 ...

  4. Spring Boot @Trasactionl 失效, JDK,CGLIB动态代理

    来自: https://www.cnblogs.com/sweetchildomine/p/6978037.html?utm_source=itdadao&utm_medium=referra ...

  5. as3的全屏功能的实现主要是舞台stage的displayState属性

    StageDisplayState.NORMAL                                               正常 StageDisplayState.FULL_SCR ...

  6. Java并发知识(2)

    1. 什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)? 原子操作是指一个不受其他操作影响的操作任务单元.原子操作是在多线程环境下避免数据不一致 ...

  7. playbook相关

    ansible-playbook site.yml  -f 10 ansible-playbook常用参数说明: -f  10          启用10个并发进程数执行playbook -u  RM ...

  8. Mysql binlog二进制日志

    Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的实际原sql语句都会被记录在binlog中. 优点:不需要记录每一 ...

  9. 基于Sentinel的Redis3.2高可用方案

    默认情况下,Redis node和sentinel的protected-mode都是yes,在搭建集群时,若想从远程连接redis集群,需要将redis.conf和sentinel.conf的prot ...

  10. VCL编写笔记整理

    unit hzqEdit1; interface uses  SysUtils, Classes, Controls, StdCtrls; type  TEditDataType = (dtpStri ...