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
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.
题意:
给出N个数,求排列中任意一个
i,(1≤i<N),a[i]∗a[i+1]
i
,
(
1
≤
i
<
N
)
,
a
[
i
]
∗
a
[
i
+
1
]
不是完全平方数的方案数
题解:
相当于限制一些数不能相邻的合法排列数.
可以先把不能排在一起的数分类,一个类别中的数两两相乘都是完全平方数,当然一个数只会出现在一个类别中.总共分了 M M 类,第类的大小为 size[i] s i z e [ i ]
假设已经处理好了,接下来依次加入每一类,形成合法排列的策略是:用当前的类中一部分数去隔开之前排列中两个相邻的同类的数,其他的插入合法的位置.那么可以设 dp[i][j] d p [ i ] [ j ] 为已有第 i i 个类时,需要隔开个相邻的同类数的方案数,前 i i 个类一共个数字,目标是 dp[M][0] d p [ M ] [ 0 ]
具体的转移:
- 将第 i+1 i + 1 类分成 k k 组,一部分(组)去隔数,一部分留下插入排列中合法的位置,(组内的排列之后计算)
- 将 p p 组插入个相邻同类数中间,前面排列的相邻同类数会减少到 j−p j − p ,但是因为加入了第 i+1 i + 1 组,所以会多出 size[i+1]−k s i z e [ i + 1 ] − k 个相邻的同类数,这样下一状态就是 dp[i+1][j−p+size[i+1]−k] d p [ i + 1 ] [ j − p + s i z e [ i + 1 ] − k ]
- 接下来是组合数:
- 从 size[i+1] s i z e [ i + 1 ] 中分 k k 组,相当于个隔板中选 k−1 k − 1 个,即 Ck−1size[i+1]−1 C s i z e [ i + 1 ] − 1 k − 1
- 在 j j 组相邻的同类数中,选个插进去, Cpj C j p
- 还剩下 k−p k − p 个,插入前 i i 形成的排列中剩下个合法位置,即 Ck−pSUM−j+1 C S U M − j + 1 k − p
- 因为我们只是依次插入当前组的数,具体位置可以选择,而非先插入的组一定在排列中的前面,也就是说插入组的顺序没有影响,但是为了插入时有足够的位置,方便起见,可以按 size s i z e 从大到小插入
转移方程是:
dp[i+1][j−p+size[i+1]−k]=dp[i][j]∗Csize[i+1]−1k−1∗Cpj∗Ck−pSUM−j+1
d
p
[
i
+
1
]
[
j
−
p
+
s
i
z
e
[
i
+
1
]
−
k
]
=
d
p
[
i
]
[
j
]
∗
C
s
i
z
e
[
i
+
1
]
−
1
k
−
1
∗
C
j
p
∗
C
S
U
M
−
j
+
1
k
−
p
然后因为每个组内可以内部排序(前面有提到),所以在计算
ans
a
n
s
时,要乘每个
size
s
i
z
e
的全排列
处理分类:
把每个数中偶数次方的因子去除,剩下来的数中只有值相同的能组成完全平方,所以把处理后相同的数分为一组即可