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. 二、vue组件化开发(轻松入门vue)

    轻松入门vue系列 Vue组件化开发 五.组件化开发 1. 组件注册 组件命名规范 组件注册注意事项 全局组件注册 局部组件注册 2. Vue调试工具下载 3. 组件间数据交互 父组件向子组件传值 p ...

  2. java Date操作的相关代码

    /** * 获取现在时间,这个好用 * * @return返回长时间格式 yyyy-MM-dd HH:mm:ss */ public static Date getSqlDate() { Date s ...

  3. 多线程编程<五>

    1 /** 2 * 中断线程:当线程由于调用sleep(),join(),wait()而暂停时,如果中断它,则会收到一个InterruptedException异常. 3 * 调用Thread.isI ...

  4. CentOS7中apache的部署与配置

    一.apache的部署 输入命令 yum list | grep httpd 查看可安装的软件包,选择"httpd.x86_64"安装. 输入命令 yum install http ...

  5. minicom-linux下USB转串口配置

    现在的笔记本越做越薄,好些电脑已经没有串口了,做硬件开发会非常头疼,不过有了USB转串口设备,PC机只需要有USB接口就可以了.在linux下我们使用minicom与目标设备通信,在此记录一下linu ...

  6. Focal Loss(RetinaNet)笔记 一种减小类别不平衡影响的方法

    Paper: https://arxiv.org/abs/1708.02002 还参考了:https://www.jianshu.com/p/8e501a159b28 其中p是预测属于某类的概率.

  7. 在按照ROS官方步骤操作,同时用Git管理整个过程,git clone的新catkin_ws报错: catkin_package() include dir 'include' does not exist relative to

    在按照ROS官方步骤操作,同时用Git管理整个过程,git clone的新catkin_ws报错如下: CMake Error at /opt/ros/kinetic/share/catkin/cma ...

  8. 去除所有js,html,css代码

    <?php$search = array ("'<script[^>]*?>.*?</script>'si", // 去掉 javascript ...

  9. adb 常用命令大全(3)- 查看手机设备信息

    查看手机型号 adb shell getprop ro.product.model 查看电池状况 adb shell dumpsys battery 其中 scale 代表最大电量,level 代表当 ...

  10. k8s架构与组件详解

    没有那么多花里胡哨,直接进行一个K8s架构与组件的学习. 一.K8s架构 k8s系统在设计是遵循c-s架构的,也就是我们图中apiserver与其余组件的交互.在生产中通常会有多个Master以实现K ...