鞍山热身赛的题,也是去年多校原题

题目大意:

求n个数的排列中满足相邻两个数互质的排列的数量并取模

当时的思路就是状压dp.. dp[i][state]  state用二进制记录某个数是否被取走,i 表示当前序列末尾的数字

然后gcd状态转移

可是n是28,算了一下有几亿个状态。。没法做。。

回来之后找了题解发现可以用数学方法优化,于是搞了半天终于ac了

首先在这个问题中:

两个数是否互质只与他们的质因数有关,所以质因数相同的数是等价的,称作此问题的等价类

质因数找到这些等价类,并得到每个类中的数的数量是很容易的。。

所以只需要对这些等价类进行处理,最后对每个等价类再乘以数量的排列数就可以得到答案了。

不过此时有了数量,就不能用二进制状压了,应该采用哈希来状压。

研究了一会发现哈希状压和二进制状压差不多,只不过把基数从(1+1)^n变成了 (num[1]+1)*(num[2]+1)....也是很好理解的

这些状态处理完,发现对于n=28只有 5600000个状态了,等价类数是17 所以复杂度是17*5600000

一交MLE了。由于取模最大30000,把数组改为short,中间结果int防溢出,不爆内存了。

然后时限30s,以为可以过,结果又T了。。

于是又想了一会,发现17,19,23这三个数与其他任意一个数的互质。。所以他们与 1 是等价的

加了这个优化以后复杂度下降到约为 14*1800000

8800ms AC...

代码如下

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int prime[]={,,,,,,,,};
const int np=;
int state[];
int g[][];
int vi[];
int num[];
int base[];
short dp[][];
bool ok[];
int n,m,ns,st;
void ini()
{
scanf("%d%d",&n,&m);
memset(g,,sizeof(g));
memset(vi,,sizeof(vi));
memset(num,,sizeof(num));
ns=;
state[++ns]=;
num[ns]=;
for(int i=;i<=n;i++)
{
st=;
if(ok[i])
{
num[]++;
continue;
}
for(int j=;j<np;j++)
{
if(i%prime[j]==)
{
st|=(<<j);
}
}
if(!vi[st])
{
state[++ns]=st;
num[ns]=;
vi[st]=ns;
}
else
{
num[vi[st]]++;
}
}
for(int i=;i<=ns;i++)
{
for(int j=;j<=ns;j++)
{
if((state[i]&state[j])==)
g[i][j]=;
}
}
base[]=;
st=;
for(int i=;i<=ns;i++)
{
base[i+]=base[i]*(num[i]+);
st+=base[i]*num[i];
}
}
int getnum(int i,int x)
{
int res=(x%base[i+])/(base[i]);
return res;
}
int getstate(int i,int num)
{
return num*base[i];
}
void dfs(int t,int x)
{
if(t==)
{
dp[x][]=;
return ;
}
if(dp[x][t]!=-)
return;
dp[x][t]=;
for(int i=;i<=ns;i++)
{
if(g[x][i]&&getnum(i,t)>=)
{
dfs(t-base[i],i);
dp[x][t]=((int)dp[x][t]+dp[i][t-base[i]])%m;
}
}
return;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int T;
scanf("%d",&T);
memset(ok,,sizeof(ok));
ok[]=;
ok[]=;
ok[]=;
while(T--)
{
ini();
memset(dp,-,sizeof(dp));
int ans=;
for(int i=;i<=ns;i++)
{
dfs(st-base[i],i);
ans=((int)ans+dp[i][st-base[i]])%m;
}
for(int i=;i<=ns;i++)
{
while(num[i]>)
{
ans=((int)ans*num[i])%m;
num[i]--;
}
}
printf("%d\n",ans);
}
}

hdu4623:crime 数学优化dp的更多相关文章

  1. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  2. P2120 [ZJOI2007]仓库建设 斜率优化dp

    好题,这题是我理解的第一道斜率优化dp,自然要写一发题解.首先我们要写出普通的表达式,然后先用前缀和优化.然后呢?我们观察发现,x[i]是递增,而我们发现的斜率也是需要是递增的,然后就维护一个单调递增 ...

  3. 【学习笔记】动态规划—斜率优化DP(超详细)

    [学习笔记]动态规划-斜率优化DP(超详细) [前言] 第一次写这么长的文章. 写完后感觉对斜优的理解又加深了一些. 斜优通常与决策单调性同时出现.可以说决策单调性是斜率优化的前提. 斜率优化 \(D ...

  4. 洛谷P2365/5785 任务安排 题解 斜率优化DP

    任务安排1(小数据):https://www.luogu.com.cn/problem/P2365 任务安排2(大数据):https://www.luogu.com.cn/problem/P5785 ...

  5. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  6. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  7. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  8. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  9. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

随机推荐

  1. 关于Spring配置 (Cannot find class [org.apache.commons.dbcp.BasicDataSource] 问题)

    myeclipse抛出异常 org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find /webapps/t ...

  2. Python进阶(面向对象编程基础)(四)

    1.方法也是属性 我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象: class Person(object): def __init__(self, name, score) ...

  3. Android 之 资源文件的介绍及使用

    Android 之 资源文件的介绍及使用 1.资源的简单介绍:  在res文件夹中定义:字符串.颜色.数组.菜单.图片.视频等:在应用程序中使用这些资源.  2.使用资源的长处:降低代码量,同一时候为 ...

  4. structured sparsity model

    Data representation往往基于如下最小化问题:         (1) 其中X是观测到的数据的特征矩阵,D是字典,Z是字典上的描述.约束项和使得字典dictionary和描述code具 ...

  5. RecycleView 瀑布流滑动移位

    RecycleView StaggeredLayoutManager(瀑布流)滑动的时候,默认会出现item移动的问题,需以下来个步骤来解决: 附上StaggeredLayoutManager中的一段 ...

  6. 使用.NET框架、Web service实现Android的文件上传(二)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYUAAAKpCAIAAADcx6fPAAAgAElEQVR4nOydd1hT5+LHg1attbfr1t ...

  7. c - 输出 101 至 200之间的素数.

    #include <stdio.h> #include <math.h> //判断 101-200 之间有多少个素数,并输出所有素数. int main(void) { , e ...

  8. android 自定义view之 TypeArray

    在定义view的时候,我们可以使用系统提供的属性,也可以自定义些额外的属性来设置自定义view的样式,这个时候,我们就需要TypeArray,字面意思就是Type 数组. 今天我们就讲讲如何自定义Vi ...

  9. iOS_SN_CoreData(二)

    上一篇是讲怎么进行CoreData的基本操作,这一篇是讲NSFetchedResultsController得到CoreData数据怎么与tableView完美结合,和动画操作的实现. NSFetch ...

  10. AjaxPro.2.dll使用方法简介

    1.添加对 AjaxPro.2.dll 的引用 2.在 webconfig 中 system.web 节点下 进行如下配置 <httpHandlers> <add verb=&quo ...