Codeforces 840C. On the Bench

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,(1i<N),a[i]a[i+1] i , ( 1 ≤ i < N ) , a [ i ] ∗ a [ i + 1 ] 不是完全平方数的方案数
题解:
相当于限制一些数不能相邻的合法排列数.

可以先把不能排在一起的数分类,一个类别中的数两两相乘都是完全平方数,当然一个数只会出现在一个类别中.总共分了 M M 类,第i类的大小为 size[i] s i z e [ i ]

假设已经处理好了,接下来依次加入每一类,形成合法排列的策略是:用当前的类中一部分数去隔开之前排列中两个相邻的同类的数,其他的插入合法的位置.那么可以设 dp[i][j] d p [ i ] [ j ] 为已有第 i i 个类时,需要隔开j个相邻的同类数的方案数,前 i i 个类一共SUM个数字,目标是 dp[M][0] d p [ M ] [ 0 ]

具体的转移:

  • 将第 i+1 i + 1 类分成 k k 组,一部分(p组)去隔数,一部分留下插入排列中合法的位置,(组内的排列之后计算)
  • p p 组插入j个相邻同类数中间,前面排列的相邻同类数会减少到 jp j − p ,但是因为加入了第 i+1 i + 1 组,所以会多出 size[i+1]k s i z e [ i + 1 ] − k 个相邻的同类数,这样下一状态就是 dp[i+1][jp+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 组,相当于size[i+1]1个隔板中选 k1 k − 1 个,即 Ck1size[i+1]1 C s i z e [ i + 1 ] − 1 k − 1
    • j j 组相邻的同类数中,选p个插进去, Cpj C j p
    • 还剩下 kp k − p 个,插入前 i i 形成的排列中剩下SUMj+1个合法位置,即 CkpSUMj+1 C S U M − j + 1 k − p
  • 因为我们只是依次插入当前组的数,具体位置可以选择,而非先插入的组一定在排列中的前面,也就是说插入组的顺序没有影响,但是为了插入时有足够的位置,方便起见,可以按 size s i z e 从大到小插入

转移方程是: dp[i+1][jp+size[i+1]k]=dp[i][j]Csize[i+1]1k1CpjCkpSUMj+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 的全排列

处理分类:
把每个数中偶数次方的因子去除,剩下来的数中只有值相同的能组成完全平方,所以把处理后相同的数分为一组即可

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值