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. 远程连接mysql出现"Can't connect to MySQL server 'Ip' ()"的解决办法

    1.大多是防火墙的问题(参考链接:https://blog.csdn.net/jiezhi2013/article/details/50603366) 2.上面方法不能解决,不造成影响情况下可关闭防火 ...

  2. Python分支结构你真的搞定了吗?

    分支结构 分支结构能够让计算机像人一样进行思考,应对不同的场景做出不同的回应. Python中不支持switch语法,目前仅支持if/else形式,但是在Python3.10的测试版本中,貌似支持了s ...

  3. Spring MVC工作原理及源码解析(四) ViewResolver实现原理及源码解析

    0.ViewResolver原理介绍 根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Mode ...

  4. Kubernetes入门,使用minikube 搭建本地k8s 环境

    这是一篇 K8S 的 HelloWorld,在学习K8S官方文档时搭建环境搭建的一个记录,照着文档下来还是比较顺利的. 一.安装kubectl 下载 kubectl curl -LO "ht ...

  5. BugkuCTF——wp(旧版)

    title: BugkuCTF--wp(旧版) date: 2020-4-25 tags: CTF,比赛 categories: CTF 比赛 Web篇 0x001-web2 解题思路: 1.直接按F ...

  6. 4.启动虚拟机 设置CentOS7

    启动虚拟机 CentOS设置 1.点击箭头方向即可启动我们的VMware 2.设置语言 在第一步设置完成后,我们一直等待,即可来到语言设置界面 此处我们设置[中文] 3.设置安装信息 将下面带有[感叹 ...

  7. [bug] org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2

    原因 SpringBoot启动加载yml配置文件出现编码格式错误 参考 https://www.pianshen.com/article/2431144034/

  8. BUUCTF(十一)[极客大挑战 2019]Knife

    BUUCTF系列 想着应该不会这么简单吧... 结果就是这么简单ee 疯狂暗示... url:xxx/index.php 密码:Syc 连接成功... cd / ls cat flag

  9. 攻防世界(十)NewsCenter

    攻防世界系列 :NewsCenter 方法一 1.打开题,看到搜索框首先想到的是sql注入 2.检查注入点 -1' union select 1,2,3# 存在注入漏洞 3.查库 附:Sql注入常见语 ...

  10. 76-Java安装Eclipse并创建第一个HelloWorld.md

    76-Java安装Eclipse并创建第一个HelloWorld.md 首先确定已经安装Java系统环境,若未安装,请参考博客Java环境windows搭建 访问Eclipse官网 下载完成直接发送快 ...