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. 随着firefox的迭代更新:FireBug不能用了?使用火狐Try Xpath插件替代Firebug和Firepath

    本篇文章讲解如何在火狐中安装和使用Try Xpath(插件替代Firebug和Firepath). 在火狐中安装Try Xpath 1. 打开火狐浏览器 FireFox57以上的版本 2. 在火狐菜单 ...

  2. selenium+python自动化90-unittest多线程执行用例

    前言 假设执行一条脚本(.py)用例一分钟,那么100个脚本需要100分钟,当你的用例达到一千条时需要1000分钟,也就是16个多小时... 那么如何并行运行多个.py的脚本,节省时间呢?这就用到多线 ...

  3. linux获取日志指定行数范围内的内容

    假如我要获取“浅浅岁月拂满爱人袖”到“落入凡尘伤情着我”之间的内容. 1.首先得到他们所在的行号: -n选项显示行号 但是有时候grep后显示的是“匹配到二进制文件(标准输入)”,说明搜索的字符串在某 ...

  4. 过滤器 ;spring拦截器 切片 小结

    1. springMVc的拦截器 实现HandlerInterceptor接口,如下: public class HandlerInterceptor1 implements HandlerInter ...

  5. as3 加载库声音报错

    排除法:(依次排序,从简单到难) 1.引用的声音类名与声音链接名字是否一致,可trace声音对象字符串检验 2.引用的声音对象是否不存在 ,可trace声音对象检验 3.最后检验是否当前swf中,其中 ...

  6. TortoiseGit 使用 HTTP 方式每次 PUSH 无需输入密码的方法

    由于 BitBucket 被墙,导致使用时只能用HTTPS代理的方式,但TortoiseGit貌似没有记忆密码的功能,以至于每次push时都要求输入密码,很是麻烦!在网上搜到的保存密码的方式也有点笨. ...

  7. How to read very large text files fast

    Question Does anyone know the fastest way to read large text files (10Mb) into a string.Readln is ju ...

  8. Python递归的经典案例

    目录 : 一.递归的简介 二.递归的经典应用   2.1 递归求阶乘   2.2 递归推斐波那契数列   2.3 二分法找有序列表指定值   2.4 递归解汉诺塔 前言: 当我们碰到诸如需要求阶乘或斐 ...

  9. Process ProcessThread Thread

    Process ProcessThread: Process and ProcessThread objects have a ProcessorAffinity property of IntPtr ...

  10. go,函数作为参数类型

    package main import "fmt" type testInt func(int) bool // 声明了一个函数类型 func isOdd(integer int) ...