SDOI2015 排序

今天看到这道题,没有一点思路,暴力都没的打。。。还是理解错题意了,操作不同位置不是说改不同的区间,而是不同操作的顺序。。。考场上如果知道这个的话最少暴力拿一半啊,因为正解本来就是暴力。。

DFS

题目问的是方案数,如果操作确定了是谁的话顺序是无所谓的,压一个A(n n)加上就好。这一点很显然,不管怎么移动,如果先一后二可以,那么先二后一也是可以的。找规律就好。

现在需要做的是找到不同的操作序列,这里的不同不是指顺序,而是指种类。因为上面说了顺序无影响,那我们可以从最小的开始,能换就换,说白了就是暴搜%%%XIN队。

暴搜的话肯定要砍大树的,上面的思路如果大力搞的话必暴,其实在枚举序列找不满足递增顺序的区间时,如果区间数>2了,直接return。因为每种操作只有一次,一次肯定换不了两个以上的区间。如果没有不满足递增的区间,说明不需要这个操作,直接整一个DFS(x+1,num){x代表当前是第几个操作,num表示用了几个操作。}如果只有一个,那就自己换一下就OK。如果有两个,那么自己跟自己块里的两段肯定不能换,因为还有另一个块不合法,自己换了那人家怎么办。所以是2×2,枚举去换,换了后检查合法性如果合法就DFS(x+1,num+1)否则不用管。还有记得回溯的时候把换了的再给人换回去

。这样这道题就AC了。

不过苣蒻还是不懂玄学复杂度,明明是2^24,虽然远远达不到这个水平,但也不至于40ms就跑完了吧,一个点才2ms,这不是a+b的时间吗哈哈。

code有些冗长了,四种情况其实可以写函数的,我直接摆在那了,反正也是打一个然后复制粘贴,不过我好像改变量时少改了一个,调了好长时间。。算了,懒得改代码了,就这样吧。

#include<bits/stdc++.h>
using namespace std;
int n,a[1000101],ans=0;
inline void fr(){freopen("c.in","r",stdin);}
inline void sc(){scanf("%d",&n);}
namespace AYX
{ inline void dfs(int x,int num)
{ if(x==n+1)
{ int l=1;
for(int i=num;i;--i)
l*=i;
ans+=l;
return;
}
int len=(1<<(x)),kk=(1<<(x-1)),m1,m2,cnt=0;
for(int i=1;i<=(1<<n)-len+1;i+=len)
{ for(int j=i;j<(1<<x)/2+i;++j)
{ if(a[j]+kk!=a[j+kk])
{ ++cnt;
if(cnt==1)
m1=i;
else
m2=i;
break;
}
if(cnt>2)return;
}
}
if(cnt>2)return;
if(cnt==0)
{ dfs(x+1,num);
return ;
}
if(cnt==1)
{
for(int i=m1;i<=m1+kk-1;++i)
swap(a[i],a[i+kk]);
dfs(x+1,num+1);
for(int i=m1;i<=m1+kk-1;++i)
swap(a[i],a[i+kk]);
return;
}
bool bo=0;
int mm1=m1+kk,mm2=m2+kk;
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[m2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[m2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[m2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[m2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[mm2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[mm2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[mm2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[mm2+i-1]);
}
inline void work()
{ for(int i=1;i<=(1<<n);++i)scanf("%d",&a[i]);
dfs(1,0);printf("%d\n",ans);
}
inline short main()
{sc();work();return 0;}
}
signed main()
{return AYX::main();}

APIO2016 划艇

看到T2好像还可做,就仔细想了很长时间,想到了f[i][j]+=f[i-1][p] (p<=j-1),但是回头一瞧,1e9的数据。。。。。。。。。。。。。还玩个球啊,老老实实打暴力。但是n最小是100,显然没有暴力分。。。。。。。。。

好吧好吧,那就不属于我了,1e9也想过离散化,可是后面就没什么进展了。

DP

dp的话得先把1e9的问提解决掉,要不然没法搞,没错,肯定要离散化。可是离散化了后我怎么整呢,原本是实在的位置,现在就是一群无情的数字。额,其实这数字还是有情的唉,他能断开不同的区间,我们求每一段区间的贡献就好了。

啥?区间贡献,这不更没法搞了哈哈。仔细想一下,本段区间对i点的贡献,跟推出来的那个式子好像很有关系的,我们只需要知道i前面有几个点也在区间j内,比如说现在到了k点,他可以在区间j内,因为k到i之间的点是可以取0的,所以不用管他,我们只关心在k和i之间可以有几个点出现在区间j内就好,那么这里每一个k的贡献就是k之前的点在j-1之前区间的方案数×k到i的m个点在j内的方案数,前者好说,我们递推过来就求过了,关键是看后者。

对于长度为len的区间,任取m个位置ans就是C(len,m),但是现在问题是我不一定m个点都取位置,他可以不参赛的,也就是在中间夹着0呢。因为0对递增是无影响的所以我完全可以想像为在len区间里塞了m个0,但是i点得在,那么就是塞了m-1个0,这样的话方案数就是C(len+m-1,m)。

好了,这样dp就解决了,因为我do时用的是i点的前j个区间,所以数组要维护前缀和,又因为我的区间是从小到大推过来的,更新了j后j-1就没有用了,所以我们可以隐去第二维,这样省很多空间。最后ans就是所有的g数组加一起,因为后面的点都可以为0的,所以对于每一个1到i都算新方案。

%%%@yspm

#include<bits/stdc++.h>
#define int long long
#define low(x) lower_bound(c+1,c+1+tot,x[i])-c
using namespace std;
const int mod=1e9+7;
int n,len,a[505],b[505],c[1015],num,sum[505]={1},C[505]={1},inv[505]={0,1},ans;
inline void fr(){freopen("c.in","r",stdin);}
inline void sc(){scanf("%lld",&n);}
namespace AYX
{ inline void work()
{ for(int i=1;i<=n;++i)scanf("%lld%lld",&a[i],&b[i]),c[++num]=a[i],c[++num]=++b[i];
for(int i=2;i<=n;++i)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
sort(c+1,c+1+num);
int tot=unique(c+1,c+1+num)-c-1;
for(int i=1;i<=n;++i)
a[i]=low(a),b[i]=low(b);
for(int j=1;j<tot;++j)
{ int len=c[j+1]-c[j];
for(int i=1;i<=n;++i)C[i]=(((C[i-1]*(len+i-1))%mod)*inv[i])%mod;
for(int i=n;i;--i)
{ if(a[i]<=j and b[i]>=j+1)
{ int f=0,m=1,cc=len;
for(int k=i-1;k>=0;--k)
{ f=(f+cc*sum[k])%mod;
if(a[k]<=j and b[k]>=j+1)cc=C[++m];
}
sum[i]=(sum[i]+f)%mod;
}
}
}
for(int i=1;i<=n;++i)ans=(ans+sum[i])%mod;
printf("%lld",ans);
}
inline short main()
{sc();work();return 0;}
}
signed main()
{return AYX::main();}

CQOI2011 放棋子

很明显的dp题。算是组合计数类dp吧。

一个很妙的地方,一个棋子占据一行一列,我们去掉这一行一列,状态变为(n-1)* (m-1)的棋盘,这算是dp的一个子状态,递推的味道很浓。

我们考虑当前到了第k个颜色,f[i][j][k]表示前k种颜色占据了i行j列,这i和j只是个数,具体位置任意。那么f[i][j][k]=f[l][r][k-1]* g[i-l][j-r]* c[n-l][i-l]* c[m-r][j-r].

组合数很好理解,都说了ij是任意的。那g是啥呢???

g表示对于第k种颜色的c[k]个棋子,占据i行j列的方案数,这里的i和j也是任意的哦。

g全部的方案明显为C(i* j,c[k]),可是这么着放不一定占全了这i行j列,怎么办?减去不合法的呗。g[i][j]-=g[l][r]* C(i,l)* C(j,r).(l<i or r<j)同样也是递推的。

有人就疑问了,为什么有两次组合数呢?其实很好理解,推g数组时l和r是在一个确定的i和j里选的,也就是说这个组合数是l和r相对于i和j的小范围的,而f数组的组合数是相对整张棋盘的。

好了,本题到此结束。

code

#include<bits/stdc++.h>
#define int long long
#define m(x) memset(x,0,sizeof(x))
using namespace std;
const int mod=1000000009;
int n,m,C,ans,num[11],c[901][901],f[31][31][31],g[31][31];
inline void fr(){freopen("c.in","r",stdin);}
inline void sc(){scanf("%lld%lld%lld",&n,&m,&C);}
namespace AYX
{
inline void work()
{ for(int i=1;i<=C;i++)scanf("%lld",&num[i]);
for(int i=0;i<=n*m;++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;
}
f[0][0][0]=1;
for(int k=1;k<=C;++k)
{ m(g);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{ if(i*j>=num[k])
{ g[i][j]=c[i*j][num[k]];
for(int l=1;l<=i;++l)
for(int r=1;r<=j;++r)
if(l<i or 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)
{ int nx=i-l,ny=j-r;
if(nx*ny>=num[k])
f[i][j][k]=(f[i][j][k]+((f[l][r][k-1]*g[nx][ny]%mod*c[n-l][nx])%mod)%mod*c[m-r][ny]%mod)%mod;
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
ans=(ans+f[i][j][C])%mod;
printf("%lld\n",ans);
}
inline short main()
{sc();work();return 0;}
}
signed main()
{return AYX::main();}

NOIP 模拟二 考试总结的更多相关文章

  1. 【noip模拟】考试总结

    今天睡了14个小时啊 把一星期的觉都补回来了 要不是被叫醒了 我肯定还在睡觉- - 其实现在还想睡... 集训真是伤身啊 感觉再睡就要睡成sb了 鉴于昨天被完虐(真·完虐 怒垫底) 来写篇总结 得分: ...

  2. NOIP 模拟 6 考试总结

    T1 这道题是一道裸的暴力,考场写挂了 \(5pts\) 原因竟是忘了删注释,难受 题解 T2 这道题是一道启发式合并,没想出来,拿了个暴力分跑了 题解 T3 这道题就是一道数学期望,想出来就水得很, ...

  3. NOIP 模拟九 考试总结

    T1 考场上先干的T2,最后慌慌张张没去想正解,打算把树建起来,拿70分的部分分,于是写树剖LCA,板子好像忘了,回忆了好久还模拟了好几遍才打对树剖LCA............期望70,结果0.考试 ...

  4. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  5. NOIP 模拟 10 考试总结

    T1 一道很妙的题,打暴力分也很多,但是考试的时候忘开 long long 了. 题解 T2 一道挺水的题,不过...(打挂了) 题解 T3 此题甚妙,转化真多,不过对思维是一个非常大的扩展 题解 考 ...

  6. NOIP 模拟六 考试总结

    T1辣鸡 T1就搞得这莫不愉快.. 大致题意是给你几个矩形,矩形覆盖的点都标记上,每个矩形无重复部分,求满足(x,y) (x+1,y+1)都标记过的点对数,范围1e9. 看起来很牛的样子,我确实也被1 ...

  7. NOIP 模拟五 考试总结

    T1string T1开的不错,看到这个题很激动,类似与HEOI2016排序,好像还要更简单一些,于是迅速冲了个桶排.因为洛谷上排序那道题是用桶排水的,所以我觉得没必要打线段树了,极端大数据20秒冲过 ...

  8. NOIP 模拟一 考试总结

    序列 考场上信心满满的打了nlogn的做法,我以为我稳了.据考试结束1h时发现看错题目了,打成了不连续的子序列.匆匆改了n2logn的做法.考试结束后,我发现我跪了.原来到终点才会发现我做的和人家不是 ...

  9. 2016.11.6 night NOIP模拟赛 考试整理

    题目+数据:链接:http://pan.baidu.com/s/1hssN8GG 密码:bjw8总结: 总分:300分,仅仅拿了120份. 这次所犯的失误:对于2,3题目,我刚刚看就想到了正确思路,急 ...

随机推荐

  1. python·那些不值钱的经验

    时间:2018-11-22 整理:byzqy python读写文本文件 1 # -*- coding: utf-8 -*- 2 3 def read_file(file): 4 with open(f ...

  2. T-SQL - query01_创建数据库|创建表|添加数据|简单查询

    时间:2017-09-29  整理:byzqy 本篇以"梁山好汉花名册"为例,记录MS SQLServer T-SQL语句的使用,包含命令: 创建数据库 | 删除数据库 创建表 | ...

  3. Learning ROS: Using a C++ class in Python

    http://wiki.ros.org/ROS/Tutorials/Using%20a%20C%2B%2B%20class%20in%20Python This tutorial illustrate ...

  4. 接口自动化-python+requests+pytest+csv+yaml

    本套代码和逻辑 是本人的劳动成果,如果有转载需要标注, 非常适合公司做项目的同学!!!小白也可以学哦! 1.项目目录  2.公共方法的封装 2.1如果不用配置文件 可以使用这个方法进行封装--但是有一 ...

  5. 高并发HHTP实践

    当今,正处于互联网高速发展的时代,每个人的生活都离不开互联网,互联网已经影响了每个人生活的方方面面.我们使用淘宝.京东进行购物,使用微信进行沟通,使用美图秀秀进行拍照美化等等.而这些每一步的操作下面, ...

  6. linux常用查询命令

    1 **系统** 2 # uname -a # 查看内核/操作系统/CPU信息 3 # head -n 1 /etc/issue # 查看操作系统版本 4 # cat /proc/cpuinfo # ...

  7. 远程线程注入DLL

    远程线程注入 0x00 前言 远程线程注入是一种经典的DLL注入技术.其实就是指一个新进程中另一个进程中创建线程的技术. 0x01 介绍 1.远程线程注入原理 画了一个图大致理解了下远程线程注入dll ...

  8. asp.net 工具

    http://www.jb51.net/article/92465.htm 这篇文章列出了针对ASP.NET开发人员的有用工具. 工具 1.Visual Studio Visual Studio Pr ...

  9. 利用nginx 来实现内网yum源(反向代理)

    简介 在项目部署时,尤其是在政府企业,对于外网简直是奢望,但是对于运维来说,没有外网的话只能自建yum源.我今天来说的是一种简单的自建yum源方法,前提是必须有一台内外网都有的机器,我们一般称为前置机 ...

  10. 在C++11编译环境中,简单自测了一下C++标准库中的string/vector和迭代器,记录一下

    #include <iostream> #include <vector> using namespace std; int main() { //////////////// ...