On the Bench

两个数如果所有质因子的奇偶性相同则是同一个数,问题就变成了给你n个数, 相同数字不能相邻的方案数。

dp[ i ][ j ]表示前 i 种数字已经处理完, 还有 j 个位置需要隔开的方案数。

转移的话, 我们枚举第i + 1种数字分成的段数, 然后枚举有几段插到 j 个空格里面, 然后转移。

最后乘上各种数字个数的阶乘。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < ) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} int n, cnt, a[N], c[N];
int g[N][N], sum[N];
int dp[N][N];
ull hs[N];
map<int, int> Map;
vector<ull> oo; int F[N], Finv[N], inv[N]; void init() {
inv[] = F[] = Finv[] = ;
for(int i = ; i < N; i++) inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
for(int i = ; i < N; i++) F[i] = 1LL * F[i - ] * i % mod;
for(int i = ; i < N; i++) Finv[i] = 1LL * Finv[i - ] * inv[i] % mod;
}
int comb(int n, int m) {
if(n < || n < m) return ;
return 1LL * F[n] * Finv[m] % mod * Finv[n - m] % mod;
}
int main() {
init();
scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
Map.clear();
for(int j = ; j * j <= a[i]; j++) {
if(a[i] % j) continue;
while(a[i] % j == ) {
Map[j]++;
a[i] /= j;
}
}
if(a[i] > ) Map[a[i]]++;
for(auto& t : Map) {
if(t.se & ) {
hs[i] *= ;
hs[i] += t.fi;
}
}
oo.push_back(hs[i]);
}
sort(ALL(oo));
oo.erase(unique(ALL(oo)), oo.end());
for(int i = ; i <= n; i++) a[i] = lower_bound(ALL(oo), hs[i]) - oo.begin() + ;
for(int i = ; i <= n; i++) c[a[i]]++;
cnt = n;
n = SZ(oo);
for(int i = ; i <= n; i++) sum[i] = sum[i - ] + c[i];
g[][] = ;
for(int i = ; i <= cnt; i++) {
for(int j = ; j <= cnt; j++) {
if(!g[i][j]) continue;
for(int k = ; i + k <= cnt; k++) {
add(g[i + k][j + ], g[i][j]);
}
}
}
dp[][c[] - ] = ;
for(int i = ; i < n; i++) {
for(int j = ; j <= cnt; j++) {
if(!dp[i][j]) continue;
int num = c[i + ];
for(int k = ; k <= num && k <= sum[i] + ; k++) {
int way = g[num][k];
for(int z = max(, k - sum[i] - + j); z <= k; z++) {
add(dp[i + ][j - z + num - k], 1LL * way * comb(j, z) % mod * comb(sum[i] + - j, k - z) % mod * dp[i][j] % mod);
}
}
}
}
int ans = dp[n][];
for(int i = ; i <= n; i++)
ans = 1LL * ans * F[c[i]] % mod;
printf("%d\n", ans);
return ;
} /*
*/

Codeforces 840C On the Bench dp的更多相关文章

  1. CodeForces 840C - On the Bench | Codeforces Round #429 (Div. 1)

    思路来自FXXL中的某个链接 /* CodeForces 840C - On the Bench [ DP ] | Codeforces Round #429 (Div. 1) 题意: 给出一个数组, ...

  2. Codeforces 840C - On the Bench(dp/容斥原理)

    Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2500 的 D1C,可个人认为难度堪比某些 *2700 *2800. 不过嘛,*2500 终究还是 *2500,还是被我自己 ...

  3. codeforces 429 On the Bench dp+排列组合 限制相邻元素,求合法序列数。

    限制相邻元素,求合法序列数. /** 题目:On the Bench 链接:http://codeforces.com/problemset/problem/840/C 题意:求相邻的元素相乘不为平方 ...

  4. Codeforces 840C. On the Bench 动态规划 排列组合

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF840C.html 题解 首先,我们可以发现,如果把每一个数的平方因子都除掉,那么剩下的数,不相等的数都可以相 ...

  5. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  6. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

  7. codeforces 721C (拓排 + DP)

    题目链接:http://codeforces.com/contest/721/problem/C 题意:从1走到n,问在时间T内最多经过多少个点,按路径顺序输出. 思路:比赛的时候只想到拓排然后就不知 ...

  8. codeforces 711C Coloring Trees(DP)

    题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...

  9. codeforces 55D - Beautiful numbers(数位DP+离散化)

    D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

随机推荐

  1. 【坦克大战】Unity3D多人在线游戏(泰课的坦克大战--旋转的螺丝钉)

    [坦克大战]Unity3D多人在线游戏 http://www.taikr.com/my/course/937 1.NetworkManager的介绍: 说明:选择固定生成时会自动寻找有StartPos ...

  2. JVM运行时内存组成分为一些线程私

    JVM运行时内存组成分为一些线程私有的,其他的是线程共享的. 线程私有 程序计数器:当前线程所执行的字节码的行号指示器. Java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...

  3. 学习Spring Boot:(十五)使用Lombok来优雅的编码

    前言 Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注解实现这一目的. 正文 添加依赖 在 pom.xml ...

  4. 帝国cms 不能正常显示最新文章

    后台能正常刷新,但前台就是不能正常显示, 把网站从c盘换到d盘,好了,原来是权限的问题

  5. [SHOI2008]仙人掌图 II——树形dp与环形处理

    题意: 给定一个仙人掌,边权为1 距离定义为两个点之间的最短路径 直径定义为距离最远的两个点的距离 求仙人掌直径 题解: 类比树形dp求直径. f[i]表示i向下最多多长 处理链的话,直接dp即可. ...

  6. JSP总结(三)——JSP中九大内置对象(汇总)

    注:后缀为汇总的基本上是整理一些网上的. 一.九大内置对象分类: 1. request  请求对象 类型 javax.servlet.ServletRequest        作用域 Request ...

  7. tensorflow 语音识别报错

    cuDnn由7.1版本改为7.4.2.24版本,成功

  8. 让WinSCP和Putty一直保持连接

    转: 让WinSCP和Putty一直保持连接 2015年08月14日 01:08:19 zcczbq 阅读数:13173 标签: puttywinscp 更多 个人分类: Operation   版权 ...

  9. python的内置模块xml模块方法 xml解析 详解以及使用

    一.XML介绍 xml是实现不同语言或程序直接进行数据交换的协议,跟json差不多,单json使用起来更简单,不过现在还有很多传统公司的接口主要还是xml xml跟html都属于是标签语言 我们主要学 ...

  10. C++回顾day03---<异常>

    一:传统错误处理机制(C中通过函数返回来处理) int CalcRes(int n, int m, char ch, int& res) { ; switch (ch) { case '+': ...