Codeforces 840C 題解(DP+組合數學)

題面

傳送門:http://codeforces.com/problemset/problem/840/C
C. On the Bench
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard 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
inputCopy
3
1 2 4
outputCopy
2
inputCopy
7
5 2 4 2 4 1 1
outputCopy
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個正整數數,求將n個數排列成相鄰兩個數之積不是完全平方數的序列的方法數,結果模1000000007

分析

此題是一道綜合性題目,考察了DP,組合數學和數論知識
我們先從DP入手
在DP之前,要做一個預處理,將n個數分成size組,每組中的數相乘爲完全平方數,與其他數乘起來不能得到完全平方數的數單獨一組
如1 4 2 5 9 可以分爲{1.4.9},{2},{5}三組

接着開始推導DP方程
分解子狀態:設dp[i][j] 表示前i組數中有j個不合法的數對時的方法數(一個不合法數對即兩個數乘起來是完全平方數,如1,9)
設第i組有cnt個數,前i組一共有sum個數
第i組數的順序可以任意排列,有cnt!種排法
我們將第i組分爲k段,則產生了k個不合法的序列,分爲s段的方法數爲C(cnt-1,k-1) .可以這樣想象,在第i組數中間的cnt-1個間隔中,插入k-1個隔板,把cnt個數分爲k段

從前面j個數對不合法的中選p個數對,有C(j,p)種方法,將k組數中的p組插入到數對中,使每個數對中間有一組數,這樣就消除了p個不合法數對
如數對(1,4) 可以用插入數對(5,20)來消除
數列變成5,1,20,4

k組數中的另外(k-p)組數則另外選位置插入。在sum+1個可插入的位置(頭尾也可以插入),原來不合法的j個空缺不能插入,因此只能插入到sum+1-j個位置,有C(sum+1-j,k-p)種方法,這s-p組數本身是不合法的。
原本這cnt個數連續排在一起是不合法的,會產生cnt-1個不合法數對,但我們用k-1個隔板隔開後,有k-1個位置變成合法的了,每組數因此又會產生cnt-k個不合法位置
如:1 4 9 ,分爲{1,4},{9}插入到序列A,B,C中
A 1 4 B 9 C ,有1個位置不合法,即1,4

這樣插入過後,消除了p個不合法數對,新增了cnt-k個不合法數對,總不合法數對個數爲j-p+cnt-k個
於是我們就實現了從dp[i-1][j]到dp[j-p+cnt-k]的轉移
狀態轉移方程爲:
dp[i][jp+cntk]=dp[i][jp+cntk]+cnt!×dp[i1][j]×Ccnt1k1×Cjp×Csum+1jkp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章