time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

A year ago on the bench in public park Leha found an array of n numbers. Leha believes that permutation p is right if for all 1 ≤ i < n condition, that api·api + 1 is not perfect square, holds. Leha wants to find number of right permutations modulo 109 + 7.

Input

First line of input data contains single integer n (1 ≤ n ≤ 300) — length of the array.

Next line contains n integers a1, a2, ... , an (1 ≤ ai ≤ 109) — found array.

Output

Output single integer — number of right permutations modulo 109 + 7.

Examples
Input
3
1 2 4
Output
2
Input
7
5 2 4 2 4 1 1
Output
144
Note

For first example:

[1, 2, 4] — right permutation, because 2 and 8 are not perfect squares.

[1, 4, 2] — wrong permutation, because 4 is square of 2.

[2, 1, 4] — wrong permutation, because 4 is square of 2.

[2, 4, 1] — wrong permutation, because 4 is square of 2.

[4, 1, 2] — wrong permutation, because 4 is square of 2.

[4, 2, 1] — right permutation, because 8 and 2 are not perfect squares.

题意 :求相邻的元素相乘不为平方数的方案数(a[0]=a[1]=1, 视 a[0] 与 a[1]  不同)

思路 :

    每个数可以表示为  p1^a1 * p2^a2 * .....

    如果 两个数A,B相乘为平方数 则   a1%2 = a1' %2  ,  a2%2 = a2'%2 .....

    即 对应质因子的幂次 奇偶性相同 这样就可以划分出T组

    然后题目就转化为 T种物品 相同种类物品不能放在相邻 求方案数

    这题就变成原题 :https://csacademy.com/contest/archive/task/distinct_neighbours/statement/

            http://acm.hdu.edu.cn/showproblem.php?pid=6116

    做法为dp

    dp [ i ] [ j ]  表示  插入第 i 组的物品 出现了 左右为相同物品的空隙个数为 j   的方案数

    那 dp [ T ]  [ 0 ]  就是最终答案了

    附: cs官方题解 (原题的题解)

      First we group all the distinct values in the array. Then we can solve the problem using dynamic programming:

      Let dp[i][j] = the number of distinct arrays that can be obtained using the elements of the first i groups such that there are exactly j pairs of consecutive positions having the same value. The answer can be found in dp[distinctValues][0].

      Now let's say the sum of frequences of the first i values is X. This means the arrrays we can build using the elements from these i groups have size X, so we can insert the elments of group i + 1 in X + 1 gaps: before the first element, after the last, and between any two consecutive. We can fix the number k of gaps where we want to insert at least one element from group i + 1, but we also need to fix the number l of these k gaps which will be between elements that previously had the same value. State dp[i][j] will update the state dp[i + 1][j - l + frequence[i + 1] - k].

      The number of ways of choosing k gaps such that exactly l are between consecutive elements having the same value can be computed easily using combination formulas. We  are left with finding out the number of ways of inserting frequence[i + 1] elements in k gaps. This is also a classical problem with a simple answer: Comb(frequence[i + 1] - 1, k - 1).

    具体转移方程见代码 :

    

    

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <functional> #define mp make_pair
#define pb push_back
#define mes(a,b) memset(a,b,sizeof(a))
#define mes0(a) memset(a,0,sizeof(a))
#define lson l,mid,pos<<1
#define rson mid+1,r,pos<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define fi first
#define se second
#define sss(a) a::iterator
#define all(a) a.begin(),a.end() using namespace std; typedef double DB;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<long long ,int> pli;
typedef pair<int,long long > pil;
typedef pair<string,int> psi;
typedef pair<long long ,long long > pll; const int inf = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const int maxn = +;
const int mod = 1e9+;
LL dp[][];
LL C[][];
LL fact[];
int cnt[];
int a[];
int vis[];
int sz;
int check(LL x)
{
LL l=,r=1e9;
LL now=l;
while (l<=r){
LL mid=(l+r)>>;
if (mid*mid<=x)now=mid,l=mid+;
else r=mid-;
}
return now*now==x;
}
inline LL M(LL x)
{
return x%mod;
}
void init()
{
C[][]=;
fact[]=;
for (int i=;i<=;i++){
C[i][]=;
for (int j=;j<=i;j++){
C[i][j]=M(C[i-][j]+C[i-][j-]);
}
}
for (int i=;i<=;i++)fact[i]=M(fact[i-]*i);
}
void slove()
{
dp[][cnt[]-]=;
int lim=cnt[];
for (int i=;i<sz;i++){
for (int j=;j<lim;j++){ /// dp[i-1][j]
for (int k=;k<cnt[i];k++){/// group[i]分成k+1组 ,cnt[i]-1-k个空隙
for (int m=;m<=min(j,k+);m++){ /// 选了m个左右相同的空隙插入
dp[i][j+cnt[i]--k-m]=M(dp[i][j+cnt[i]--k-m]+dp[i-][j]*C[cnt[i]-][k]%mod*C[j][m]%mod*C[lim--j+][k+-m]);
}
}
}
lim+=cnt[i];
}
LL ans=dp[sz-][];
for (int i=;i<sz;i++){
ans*=fact[cnt[i]];
ans%=mod;
}
cout<<ans<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
scanf("%d",&n);
for (int i=;i<n;i++){
scanf("%d",a+i);
}
for (int i=;i<n;i++){
if (vis[i]==){
for (int j=i;j<n;j++){
if (check(1LL*a[i]*a[j])){
cnt[sz]++;
vis[j]=;
}
}
sz++;
}
}
init();
slove();
return ;
}

Codeforces Round #429 (Div. 2) E. On the Bench的更多相关文章

  1. Codeforces Round #429 (Div. 1) C. On the Bench(dp + 组合数)

    题意 一个长度为 \(n\) 的序列 \(A\) ,定义一个 \(1\) 到 \(n\) 的排列 \(p\) 是合法的,当且仅当 \(\forall i \in [1, n − 1], A_{p_i} ...

  2. 【做题】Codeforces Round #429 (Div. 2) E. On the Bench——组合问题+dp

    题目大意是给你n个数,求相邻两数相乘不是完全平方数的排列数. 一开始看到这题的时候,本人便想给相乘为完全平方数的数对建边,然后就写萎了... 后来通过集体智慧发现这个重要性质:对于自然数a,b,c,若 ...

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

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

  4. CodeForces 840B - Leha and another game about graph | Codeforces Round #429(Div 1)

    思路来自这里,重点大概是想到建树和无解情况,然后就变成树形DP了- - /* CodeForces 840B - Leha and another game about graph [ 增量构造,树上 ...

  5. CodeForces 840A - Leha and Function | Codeforces Round #429 (Div. 1)

    /* CodeForces 840A - Leha and Function [ 贪心 ] | Codeforces Round #429 (Div. 1) A越大,B越小,越好 */ #includ ...

  6. 【Codeforces Round #429 (Div. 2) A】Generous Kefa

    [Link]:http://codeforces.com/contest/841/problem/A [Description] [Solution] 模拟,贪心,每个朋友尽量地多给气球. [Numb ...

  7. Codeforces Round #429 (Div. 2/Div. 1) [ A/_. Generous Kefa ] [ B/_. Godsend ] [ C/A. Leha and Function ] [ D/B. Leha and another game about graph ] [ E/C. On the Bench ] [ _/D. Destiny ]

    PROBLEM A/_ - Generous Kefa 题 OvO http://codeforces.com/contest/841/problem/A cf 841a 解 只要不存在某个字母,它的 ...

  8. 【Codeforces Round #429 (Div. 2) C】Leha and Function

    [Link]:http://codeforces.com/contest/841/problem/C [Description] [Solution] 看到最大的和最小的对应,第二大的和第二小的对应. ...

  9. 【Codeforces Round #429 (Div. 2) B】 Godsend

    [Link]:http://codeforces.com/contest/841/problem/B [Description] 两个人轮流对一个数组玩游戏,第一个人可以把连续的一段为奇数的拿走,第二 ...

随机推荐

  1. (转)IntelliJ Idea 常用快捷键列表 for win

    Ctrl+Shift + Enter,语句完成 ctrl+alt+左键 进入实现方法 “!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Shif ...

  2. 手写Json转换

    在做项目的时候总是要手动将集合转换成json每次都很麻烦,于是就尝试着写了一个公用的方法,用于转换List to json: using System; using System.Collection ...

  3. EffectiveJava(28)怎么利用有限制的通配符类型来提升API的灵活性

    有时候,我们需要的灵活性要比不可变类型所能提供的更多.所以针对一些通用性的方法,通常用泛型代替固定的数据类型,特别是当你要将某个方法打包成Jar的时候. 结合之前的例子,我们增加尝试用有限制的通配符类 ...

  4. java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述

    算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...

  5. CentOS 6.4 编译安装 gcc 4.8.1(转)

    今天在isocpp上看到“GCC 4.8.1 released, C++11 feature complete”这个消息,非常兴奋.终于有一个全面支持C++11语言特性的编译器了! 当然了,gcc仅仅 ...

  6. Drupal启动过程

    Drupal整个启动过程共分为8个阶段: DRUPAL_BOOTSTRAP_CONFIGURATION:initialize configuration DRUPAL_BOOTSTRAP_PAGE_C ...

  7. FIS3项目构建

    概述 FIS3采取了类似CSS语法一样的配置风格,易于理解与上手.FIS3 是面向前端的工程构建工具.解决前端工程中性能优化.资源加载(异步.同步.按需.预加载.依赖管理.合并.内嵌).模块化开发.自 ...

  8. Name与x:Name的关系

    小序:   如果想用Google搜包含冒号的内容怎么办?比如我想搜x:Name这个字符串…… 原来,应该是这样——x::Name 这世道,连搜索也要加转义,全民程序员,要不要人活了?   正文:   ...

  9. CSS3图片折角效果

    本篇文章由:http://xinpure.com/css3-picture-angle-effect/ 图片折角效果主要是通过设置 border 属性实现的效果 效果预览 效果解析 假设我们将一个元素 ...

  10. Objective-C之定义函数

    Demo1.m 一个基础的函数定义 #import<Foundation/Foundation.h> //定义一个返回值为int类型的,名为max的函数.传入的参数为两个int型数据 in ...