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

题目大意:

求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. css的小demo

    demo1 一个高度随宽度变化的正方形   (缩小屏幕试试) 原理:margin和padding如果是用百分比设置,则是以父元素的宽度的百分比设置的. .Square{ display: inline ...

  2. Demon_Tank (坦克移动发射子弹)

    using UnityEngine; using System.Collections; public class Tank : MonoBehaviour { //子弹预设体 public Game ...

  3. 无法找到脚本引擎Jscript解决

    无法找到脚本引擎Jscript解决 CScript 错误: 无法找到脚本“InstallWizardForVS2010.js”的脚本引擎“JScript”. 目标环境:windows 7 64bit系 ...

  4. POJ 2513 Colored Sticks - from lanshui_Yang

    题目大意:给定一捆木棒,每根木棒的每个端点涂有某种颜色.问:是否能将这些棒子首位项链,排成一条直线,且相邻两根棍子的连接处的颜色一样. 解题思路:此题是一道典型的判断欧拉回路或欧拉通路的问题,以木棍的 ...

  5. SharePoint 要一个多行文本类型字段为特殊类型的链接

    1.插入在测试列表中的多行文本字段.名字叫做Content.例如下面的附图: 2.在Content字段里.加入一个Link.例如以下图: 3.尝试输入Notes格式的Link,例如以下图: 4.点击O ...

  6. samba服务日志文件-密码文件及启停

    1.Samba服务日志文件日志文件对于samba非常重要,它存储着客户端访问samba服务器的信息,以及samba服务的错误提示信息等,可以通过分析日志,帮助解决客户端访问和服务器维护等问题.在/et ...

  7. 前端bug记录---不定时更新

    在项目的开发中难免遇到各种各样的bug,我觉得还是有必要记录一下的,方便日后查询. safari window resize  为满足日常轮播需求,做一个符合当前业务的轮播插件,其中需要考虑windo ...

  8. Android -------- eclipse平台上的单元测试框架

    eclipse平台上单元测试框架 继承android.test.AndroidTestCase类 清单文件中设置 设置指令集,与application标签同级 <instrumentation ...

  9. Jenkins学习之——(1)Jenkins的安装与配置

    1.最近公司要求做自动化部署,于是自学了jenkins.这个参考书很少,网上的文章也讲得很模糊,于是打算把自己学习东西记下来,希望对大家有所帮助. 一.jenkins的安装 到jenkins官网(ht ...

  10. scala学习笔记——特质

    一个类扩展自一个或多个特质,以便使用这些特质提供的服务.特质可能会要求使用它的类支持某个特定的特性.不过和java不同,Scala特质可以给出这些特性的缺省实现. 特质的特性: 类可以实现任意数量的特 ...