5.23考试总结(NOIP模拟2)

洛谷题单

看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人

然后就急忙去干T2T3了

后来考完一看,只有\(T1\)骗到了\(15pts\)[尴尬\(.jpg\)]

\(T1\)P3322 [SDOI2015]排序

背景

说实话,看见这题正解是dfs的那一刻,我人都傻了[流泪.jpg]

在讲这题的时候赵队@yspm 类比了线段树的思想%%%%%,在食用本篇题解时可以想一下

解题思路

最基本的一个思想:结果与操作的顺序无关,因为在更换的时候无论先换哪一个最后排列都是一定的。

因此我们肯定会用到\(A_n^n\)也就是n的阶乘,需要初始化一下,这里用的jc数组记录

然后就可以 愉快 搜索了。

  • 先是check函数;

    check(x)用来检查所有长度为1<<x的块是否满足递增,

    有一个非常妙的地方:我们已经知道这个序列是由1~\(2^n\)组成的了

    因此在判断的时候只需要循环,看第i块的第一个数是否和第j块的第一个数正好差一个块长就好了

    bool check(int x)
    {
    for(int i=1;i<=(1<<(n-x));i++)
    if(s[(i-1)*(1<<x)+1]+(1<<(x-1))!=s[(i-1)*(1<<x)+(1<<(x-1))+1])
    return false;
    return true;
    }
  • 再谈交换函数:

    swap(i,j,k)表示将分别以i和j开始长度为k的序列互换

       void swap(int i,int j,int k)
    {
    for(int l=1;l<=k;l++)
    swap(s[i+l-1],s[j+l-1]);
    }
  • 最后是dfs函数

    dfs(x,num)表示交换到块长为1<<x了,并且此前进行了num个操作

    如果这个块不是单调递增的,直接return就好,毕竟他对于答案是没有贡献的

    对于x==n时表明整个序列已经整完了,然后直接给ans加上jc[num]就好了

    然后直接向下进行dfs(x+1,num)不做任何处理

    对于进行处理的情况,把整个序列两块两块的看,如果不符合条件(判断方法与上面的check同)记录到一个t数组里,一会处理,

    如果需要处理的总数超过4的话直接break,剩下的直接交给后面就可以了

    然后暴力两两枚举操作,进行交换后,直接进行下一层dfs以及回溯就好了

\(code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e3;
int n,ans,jc[13],s[N];
bool check(int x)
{
for(int i=1;i<=(1<<(n-x));i++)
if(s[(i-1)*(1<<x)+1]+(1<<(x-1))!=s[(i-1)*(1<<x)+(1<<(x-1))+1])
return false;
return true;
}
void swap(int i,int j,int k)
{
for(int l=1;l<=k;l++)
swap(s[i+l-1],s[j+l-1]);
}
void dfs(int x,int num)
{
if(x&&!check(x))
return ;
if(x==n)
{
ans+=jc[num];
return ;
}
dfs(x+1,num);
int t[5],tot=0;
for(int i=1;i<=(1<<(n-x));i+=2)
if(s[i*(1<<x)+1]!=s[(i-1)*(1<<x)+1]+(1<<x))
{
if(tot==4)
break;
t[++tot]=i;
t[++tot]=i+1;
}
if(!tot)
return ;
for(int i=1;i<=tot;i++)
for(int j=i+1;j<=tot;j++)
{
swap((1<<x)*(t[i]-1)+1,(1<<x)*(t[j]-1)+1,1<<x);
dfs(x+1,num+1);
swap((1<<x)*(t[i]-1)+1,(1<<x)*(t[j]-1)+1,1<<x);
}
}
#undef int
int main()
{
#define int long long
scanf("%lld",&n);
jc[0]=1;
for(int i=1;i<=n;i++)
jc[i]=jc[i-1]*i;
for(int i=1;i<=(1<<n);i++)
scanf("%lld",&s[i]);
dfs(0,0);
printf("%lld",ans);
return 0;
}

\(T2\)题解 P3643 [APIO2016]划艇

背景

打了挺长时间爆搜,考完一交到洛谷,TLE是小事,重点是运行了3.73min,难怪一分没有QAQ

解题思路

先想一下最简单的打法吧

用f[i][j]表示前i所学校中,第i所学校参赛,且派出j艘划艇的方案数

显然,\(f[i][j]=1+∑_{k=1}^{i-1}∑_{k=1}^{j-1}f[k][t]\)

考虑优化,我们需要的只是长度,因此可以将每个端点离散化,然后分段枚举

方案分两部分:

  1. i从(j-1)~j选一个,前面所有的学校要么不选要么从1~(j-1)区间中选,方案数为\(\sum\limits_{l=1}^{i-1}\sum\limits_{r=1}^{j-1} f[l][r]*C_{len}^1\)
  2. i从(j-1)j选一个,前面有学校也从(j-1)j中选,定第一个从(j-1)j中选的学校为k,显然总方案数为(ki的方案数)*\(\sum\limits_{l=1}^{k-1}\sum\limits_{r=1}^{j-1} f[l][r]\)

将1和2式子合并一下就可以得到\(\sum\limits_{l=1}^{i-1}\sum\limits_{r=1}^{j-1} f[l][r]+\sum\limits_{l=1}^{k-1}\sum\limits_{r=1}^{j-1} f[l][r]\)

可知ki学校一定选择j-1j中的数或者选择0,

因为k和i都从j区间中选,k+1~i-1学校可以选择j区间的如果选的话一定从j区间中选,如果不选就选0,而不可以选j区间的一定不能派划艇

有一个引理

从区间[0,L]中取n个数,要求所有非零数严格递增,则方案数为\(C_n^{L+n}\)

一看这式子,直接杨辉三角走起,再一看数据范围。。。。十分不友善,考虑一下从以前的状态中转移过来:

\(C_{n+1}^{m+1}=C_n^m*\frac{n+1}{m+1}\)

然后用前缀和维护一下

f[i][j],表示1~i学校从1~j区间选的方案总数,也就是下面的式子:

\(f[i][j]=len*f[i-1][j-1]+\sum\limits_{k=i-1}^{1} C_{l+p-2}^p*f[k-1][j-1]\)

\(code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e2+10,mod=1e9+7;
int n,cnt,ans,ys[N<<1],a[N],b[N],f[N],g[N],inv[N];
void get_INV()
{
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=((mod-mod/i)*inv[mod%i])%mod;
}
#undef int
int main()
{
#define int long long
scanf("%lld",&n);
get_INV();
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i],&b[i]);
ys[++cnt]=a[i];
ys[++cnt]=++b[i];
}
sort(ys+1,ys+cnt+1);
cnt=unique(ys+1,ys+cnt+1)-ys-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(ys+1,ys+cnt+1,a[i])-ys;
b[i]=lower_bound(ys+1,ys+cnt+1,b[i])-ys;
}
f[0]=g[0]=1;
for(int j=1;j<cnt;j++)
{
int len=ys[j+1]-ys[j];
for(int i=1;i<=n;i++)
g[i]=g[i-1]*(len+i-1)%mod*inv[i]%mod;
for(int i=n;i>=1;i--)
if(a[i]<=j&&j<b[i])
for(int k=i-1,tot=1;k>=0;k--)
{
f[i]=(f[i]+f[k]*g[tot]%mod)%mod;
if(a[k]<=j&&j<b[k])
tot++;
}
}
for(int i=1;i<=n;i++)
ans=(ans+f[i])%mod;
printf("%lld",ans);
return 0;
}

\(T3\)题解 P3158 [CQOI2011]放棋子

背景

考试的时候这个题也看了不短时间,想到了题解的一小部分,剩下的就不知道偏到哪去了,本来一开始还想整一下dp呢,到了后来直接组合数学呀,欧拉筛呀一些玄学东西,最后的测试结果也是WA,RE,TLE五花八门的。。。

解题思路

首先感谢这篇blog,以及赵队的讲解,让我懂了这个题。。。

因为n的数据比较小吗,我们的数组可以多开那么两维

  • f[i][j][k]表示前k种颜色占领了任意i行j列的方案数。

  • g[i][j][k]表示任意k枚同色棋子放任意i行j列的方案数。

g数组主要用于维护f数组

先看f数组

\(f[i][j][k]=\sum_{l=0}^{i-1}\sum_{r=0}^{j-1}f[l][r][k-1]*g[i-l][j-r][s[k]]*C^{n-l}_{i-l}*C^{m-r}_{j-r}\)

更新的条件是$(i-l)*(j-r) \ge s[k] $

\(\sum_{l=0}^{i-1}\sum_{r=0}^{j-1}\)枚举前k-1种颜色在l行r列时的情况

\(f[l][r][k-1]\)为前k-1种颜色在l行r列时的方案数

\(g[i-l][j-r][s[k]]*C^{n-l}_{i-l}*C^{m-r}_{j-r}\)则是枚举第k种颜色在i-l行j-r列的方案数

再看g数组

\(g[i][j][k]=C^{i*j}_k-\sum_{l=1}^i\sum_{r=1}^jg[l][r][k]*C_l^i*C_r^j\)

更新的条件是\(l<i||r<j\)并且\(i*j \ge k\)

\(C^{i*j}_k\)就是把i*j个数中整出来k个

由于我们要求g[i][j][k]要求记录的是把前i行前j列占满的情况,这里需要容斥一下

\(\sum_{l=1}^i\sum_{r=1}^jg[l][r][k]*C_l^i*C_r^j\)表示前i行前j列没有占满,也就是不符合条件的方案数

一些优化

显而易见,我们在求组合数时可以用杨辉三角预处理一下。

并且通过观察我们发现g数组通过在枚举种数是可以压掉最后一维节省空间。

在运算的时候要多取mod,杨辉三角求组合数尽量初始化大一些,否则连样例都过不了(别问我为什么知道,我就是知道[流泪.jpg])

code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=35,M=310,mod=1e9+9;
int n,m,t,ans,s[N],c[N*N][N*N],f[N][N][N],g[N][N];
void get_C()
{
for(int i=0;i<N*N;i++)
{
c[i][0]=1;
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
#undef int
int main()
{
#define int long long
scanf("%lld%lld%lld",&n,&m,&t);
f[0][0][0]=1;
get_C();
for(int k=1;k<=t;k++)
{
scanf("%lld",&s[k]);
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i*j>=s[k])
g[i][j]=c[i*j][s[k]];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i*j>=s[k])
for(int l=1;l<=i;l++)
for(int r=1;r<=j;r++)
if(l<i||r<j)
g[i][j]=(g[i][j]-g[l][r]*c[i][l]%mod*c[j][r]%mod+mod)%mod;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int l=0;l<i;l++)
for(int r=0;r<j;r++)
if((i-l)*(j-r)>=s[k])
f[i][j][k]=(f[i][j][k]+f[l][r][k-1]*g[i-l][j-r]%mod*c[n-l][i-l]%mod*c[m-r][j-r]%mod)%mod;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=(ans+f[i][j][t])%mod;
printf("%lld",ans%mod);
return 0;
}

5.23考试总结(NOIP模拟2)的更多相关文章

  1. 8.23考试总结(NOIP模拟46)[数数·数树·鼠树·ckw的树]

    T1 数数 解题思路 大概是一个签到题的感觉...(但是 pyt 并没有签上) 第一题当然可以找规律,但是咱们还是老老实实搞正解吧... 先从小到大拍个序,这样可以保证 \(a_l<a_r\) ...

  2. 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]

    6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...

  3. 5.22考试总结(NOIP模拟1)

    5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...

  4. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  5. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  6. 「考试」noip模拟9,11,13

    9.1 辣鸡 可以把答案分成 每个矩形内部连线 和 矩形之间的连线 两部分 前半部分即为\(2(w-1)(h-1)\),后半部分可以模拟求(就是讨论四种相邻的情况) 如果\(n^2\)选择暴力模拟是有 ...

  7. 6.11考试总结(NOIP模拟7)

    背景 时间分配与得分成反比,T1 20min 73pts,T2 1h 30pts,T3 2h 15pts(没有更新tot值,本来应该是40pts的,算是本次考试中最遗憾的地方了吧),改起来就是T3比较 ...

  8. 6.10考试总结(NOIP模拟6)

    前言 就这题考的不咋样果然还挺难改的.. T1 辣鸡 前言 我做梦都没想到这题正解是模拟,打模拟赛的时候看错题面以为是\(n\times n\)的矩阵,喜提0pts. 解题思路 氢键的数量计算起来无非 ...

  9. 6.7考试总结(NOIP模拟5)

    前言 昨天说好不考试来着,昨晚就晚睡颓了一会,今天遭报应了,也没好好考,考得挺烂的就不多说了. T1 string 解题思路 比赛上第一想法就是打一发sort,直接暴力,然后完美TLE40pts,这一 ...

随机推荐

  1. FreeSWITCH的安装与使用

    FreeSWITCH

  2. 使用Qt实现一个必应壁纸客户端

    概要 必应的每日壁纸很好看,但是看不到一周以前的壁纸图片,日前使用python开发了必应壁纸收集站,可惜这样的收集站只能在线浏览,我在想要是有一款软件能够下载每日必应壁纸,并应用到windows的桌面 ...

  3. CentOS/Linux内存占用大,用Shell脚本自动定时清除/释放内存

    CentOS/Linux内存占用大,用Shell脚本自动定时清除/释放内存来自:互联网 时间:2020-03-22 阅读:114以下情况可能造成Linux内存占用过高服务配置存在直接分配错误,或隐性分 ...

  4. 查看报错原因 sshd -t

    b for ssh.service failed because the control process exited with error code. See "systemctl sta ...

  5. 理解RESTful架构——Restful API设计指南

    理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...

  6. 大文件查找 du -ahx . | sort -rh | head -10

    # cd /root@test-W330-C30:/# du -ahx . | sort -rh | head -58.2G .5.6G ./usr3.3G ./usr/share1.9G ./usr ...

  7. DS1302应用电路

    http://www.diangon.com/wenku/rd/danpianji/201501/00017904.html

  8. 【转】Spring_IOC学习

    原文地址:http://github.thinkingbar.com/spring/ 一.XML文件语法的知识点 对于XML没有提示的话,在Eclipse中搜索XML catalog设置.对于XML文 ...

  9. 实操笔记:为 NSQ 配置监控服务的心路历程

    在 Go 语言实现的实时消息队列中, NSQ 的热度可以排第一. NSQ 这款消息中间件简单易用,其设计目标是为在分布式环境下运行,为去中心化服务提供一个强大的基础架构.它具有分布式.去中心化的拓扑结 ...

  10. Django中数据库操作相关的错误

    问题:字段修改属性发生错误 1> >python manage.py makemigrations You are trying to add a non-nullable field ' ...