SSY的队列 hash+记忆化
题目描述
\(SSY\) 是班集体育委员,总喜欢把班级同学排成各种奇怪的队形,现在班级里有 \(N\) 个身高互不相同的同学,请你求出这 \(N\) 个人的所有排列中任意两个相邻同学的身高差均不为给定整数M的倍数的排列总数。
输入格式
共三行:
第一行为 \(N\)
第二行为 \(N\) 个不同的整数
第三行为 \(M\)
输出格式
一行,为符合条件的排列总数(答案对 \(1234567891\) 取余数)。
样例
样例输入1
3
-1 0 1
2
样例输出1
2
样例输入2
4
1 2 3 4
3
样例输出2
12
数据范围与提示
\(20\%\) 的数据:\(N<=11\)
\(70\%\) 的数据:\(N<=15\)
\(100\%\) 的数据:\(N<=30,M<=1000\)。
分析
对于一个数,它原来的值和它对 \(m\) 取模之后的值在这道题中意义是相同的
所以一共只会有 \(m\) 种数
我们记录一下每一种数有多少个,然后把个数存进栈里
我们会发现,方案数仅与当前的数和剩下个数为 \(x\) 的数有几种有关
比如当 \(m=5\) 时,\(3\ 2\ 2\)和 \(3\ 1\ 1\) 的结果是完全一样的
可以设 \(f[i][j][k][...]\) 为当前选的是第 \(i\) 种数,剩下个数为 \(1\) 的数有 \(j\) 种,剩下个数为 \(2\) 的数有 \(k\) 种 ... 的方案数
数组开不下,所以我们可以用哈希的思想把状态压成一个
对于递归的每一层,开一个 \(map\) 记录一下即可
要注意的是最后要乘上每一种数个数的阶乘,因为同一种数可以任意交换位置
代码
#include<cstdio>
#include<map>
#include<algorithm>
#include<cstring>
#include<cmath>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}\
return x*fh;
}
#define ull unsigned long long
const int maxn=35;
const int mod=1234567891;
const ull bas=233333;
int a[maxn],sta[maxn],b[maxn],n,m,tp,mmax,jc[maxn];
bool vis[maxn];
std::map<ull,int> mp[maxn];
int dfs(int now,int lat){
if(now>n){
return 1;
}
memset(b,0,sizeof(b));
for(rg int i=1;i<=tp;i++){
if(i!=lat) b[sta[i]]++;
}
ull nans=sta[0];
for(rg int i=0;i<=mmax;i++){
nans=nans*bas+b[i];
}
nans=nans*bas+sta[lat];
if(mp[now].find(nans)!=mp[now].end()) return mp[now][nans];
rg int mans=0;
if(sta[0]>0){
sta[0]--;
mans=((long long)mans+(long long)dfs(now+1,0))%mod;
sta[0]++;
}
for(rg int i=1;i<=tp;i++){
if(i!=lat && sta[i]>0){
sta[i]--;
mans=((long long)mans+(long long)dfs(now+1,i))%mod;
sta[i]++;
}
}
mp[now][nans]=mans;
return mans;
}
int main(){
n=read();
for(rg int i=1;i<=n;i++){
a[i]=read();
}
m=read();
for(rg int i=1;i<=n;i++){
a[i]%=m;
if(a[i]<0) a[i]+=m;
}
rg int ncnt=0;
for(rg int i=1;i<=n;i++){
if(vis[i]) continue;
vis[i]=1;
ncnt=0;
for(rg int j=i;j<=n;j++){
if(a[i]==a[j]){
vis[j]=1;
ncnt++;
}
}
mmax=std::max(mmax,ncnt);
if(ncnt==1) sta[0]++;
else sta[++tp]=ncnt;
}
jc[0]=1;
for(rg int i=1;i<=n;i++){
jc[i]=1LL*jc[i-1]*i%mod;
}
rg int ans=1;
for(rg int i=0;i<=tp;i++){
ans=1LL*ans*jc[sta[i]]%mod;
}
ans=1LL*ans*dfs(1,0)%mod;
printf("%d\n",ans);
return 0;
}
SSY的队列 hash+记忆化的更多相关文章
- [HNOI2013]比赛 (用Hash实现记忆化搜索)
[HNOI2013]比赛 题目描述 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局, ...
- TC-572-D1L2 (双向搜索+记忆化)
solution: 这一题是比较难实现的双向搜索题:(字符串+双向搜索+hash记忆化) 我们可以先把K的前半部分枚举出来,并将得出的所有结果和题目给的n个数的每一个数的前半部分都比对一遍,得到它和每 ...
- LuoguP2254 [NOI2005]瑰丽华尔兹 (单调队列优化DP)(用记忆化过了。。。)
记忆化 #include <cstdio> #include <iostream> #include <cstring> #include <algorith ...
- FZU 2092 bfs+记忆化搜索
晚上团队训练赛的题 和普通bfs不同的是 这是同时操纵人与影子两个单位进行的bfs 由于可能发生人和影子同时接触水晶 所以不可以分开操作 当时使用node记录人和影子的位置 然后进行两重for循环来分 ...
- FZU 2092 收集水晶 bfs+记忆化搜索 or 暴力
题目链接:收集水晶 一眼看过去,觉得是普通的bfs,初始位置有两个.仔细想了想...好像如果这样的话..........[不知道怎么说...T_T] dp[12][12][12][12][210] 中 ...
- (中等) POJ 1054 The Troublesome Frog,记忆化搜索。
Description In Korea, the naughtiness of the cheonggaeguri, a small frog, is legendary. This is a we ...
- (区间dp + 记忆化搜索)Treats for the Cows (POJ 3186)
http://poj.org/problem?id=3186 Description FJ has purchased N (1 <= N <= 2000) yummy treats ...
- hdu1428 记忆化搜索(BFS预处理最短路径和+DP+DFS)
题意:有一块 n * n 大小的方形区域,要从左上角 (1,1)走到右下角(n,n),每个格子都有通过所需的时间,并且每次所走的下一格到终点的最短时间必须比当前格子走到重点的最短时间短,问一共有多少种 ...
- tyvj 1004 滑雪 记忆化搜索
滑雪 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.tyvj.cn/p/1004 Description trs喜欢滑雪.他来 ...
随机推荐
- c# 常用帮助类
C#常用帮助类 因为小土现在还是处于小白阶段,所以自己的知识技术还达不到要求,但是小土在网上找到一个大神的,等以后小土技术有了一定提升以后,在走自己的路,啥也不说了上货. 地址 :https://gi ...
- vue知识点12
知识点归纳整理如下: 1. 数组用下标改变,或者对象增加属性,这样的改变数据 是不能触发视图更新的,要用 Vue.set(对象,属性,值) 或this.$set(对象,属性,值) 2. this. ...
- java安全编码指南之:线程安全规则
目录 简介 注意线程安全方法的重写 构造函数中this的溢出 不要在类初始化的时候使用后台线程 简介 如果我们在多线程中引入了共享变量,那么我们就需要考虑一下多线程下线程安全的问题了.那么我们在编写代 ...
- VB 错误日志:MSForms.CommandButton 不是一个已加载的控件类等解决方法
是由于缺少了fm20.dll这个必要组件 网上找到 然后在工程中引用 找到路径 完美解决
- H5页面 用户启动无痕浏览本地储存 localstorage 清楚数据
移动端开发时,如果用户浏览器启用了无痕浏览,那么本地存储信息就会失效,会导致页面信息报错 解决办法: 先判断是否能适用 localStorage.setItem 如果不行在适用 cookie coo ...
- Java基础—反射与代理(新手向)
第1章 反射与代理 1.1 反射定义 一般情况下,需要一个功能的前提是遇到了某个问题,这里先列举一些问题,然后再通过反射是如何解决了这些问题,来引出反射的定义. 普通开发人员工作中最常见的问题:需要生 ...
- 什么是 RedLock
Redis 官方站这篇文章提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock,此种方式比原先的单节点的方法更安全.它可以保证以下特性: 安全特性:互斥访问,即永远只有一个 cli ...
- canvas生成圆图和微信小程序canvas圆图
先在HTML中创建 img和canvas并设置id属性 <canvas id="canvas" width="500" height="500& ...
- 3.6 栈 ADT - 3.7 队列 ADT
3.6 栈 ADT 栈是限制插入和删除只能在一个位置上进行的表,叫做栈的顶部.对栈的基本操作有进栈和出栈,进栈在顶部插入元素,出栈删除最后插入的元素. 栈是一个表,因此任何实现表的方法都能实现栈.显然 ...
- SpringMVC 直接返回中文字符串时,出现乱码(?)的问题
在springmvc.xml中加入下面配置得以解决. <mvc:annotation-driven> <mvc:message-converters> <bean cla ...