luogu 4448 & XSY 3156

luogu 4448 & XSY 3156

XSY 3156 : 额外附加了第一个元素和最后一个元素是相邻的条件。

sol：

$\frac{(\sum_i b_i)!}{\prod_i b_i!}\prod_ia_i!\binom{a_i-1}{b_i-1}(-1)^{a_i-b_i}$

$f_{i,j}=\sum_{k=1}^{\min(a_i,j)}f_{i-1,j-k}\times (-1)^{a_i-k}\frac{a_i!\binom{a_i-1}{k-1}}{k!}$

#include<algorithm>
#include<cstdio>
#include<cmath>
const int N = 3e2+7;
typedef long long LL;
#define R register
#define cerr(x) printf("%d\n", x)
const int p = 1e9+7;
int n;
int A[N*N], cnt = 0, k[N*N], sq;
LL fac[N*N], ifac[N*N];
bool dis[N][N];
inline int min(int a, int b) {
return a > b ? b : a;
}
int vis[N*N];
inline LL FST(int x, int k) {
LL res = 1;
if (!k) return 1;
if (!x) return 0;
while (k) {
if (k & 1) res = 1LL * res * x % p;
x = 1LL * x * x % p, k >>= 1;
} return res % p;
}
void dfs(int x, int col) {
vis[x] = cnt;
for (int i = 1; i <= n; i++)
if (i != x && dis[x][i] && !vis[i])
dfs(i, col);
}
void init() {
scanf("%d", &n);
for (R int i = 1; i <= n; i++)
scanf("%d", &A[i]);
std :: sort(A + 1, A + n + 1);
for (R int i = 1; i <= n; i++)
for (R int j = i + 1; j <= n; j++) {
if (dis[i][j]) continue;
LL nx = std :: sqrt(1LL * A[i] * A[j]);
if (1LL * nx * nx == 1LL * A[i] * A[j])
dis[i][j] |= 1, dis[j][i] |= 1;
}
for (R int i = 1; i <= n; i++)
if (!vis[i]) dfs(i, ++cnt);
for (R int i = 1; i <= n; i++) k[vis[i]]++;

int up = 5000;
fac[0] = 1, ifac[0] = 1;
for (R int i = 1; i <= up; i++) fac[i] = 1LL * fac[i - 1] * i % p;
ifac[up] = FST(fac[up], p - 2);
for (R int i = up - 1; i >= 1; i--) ifac[i] = 1LL * ifac[i + 1] * (i + 1) % p;
//for (R int i = 1; i <= n; i++) cerr(ifac[i]);
}
inline int cc(int n, int m) {
return 1LL * fac[n] * ifac[n - m] % p * ifac[m] % p;
}
int f[N][N];
inline int iep(int a, int b) {
return (((a - b) & 1) ? -1 : 1);
}
int main() {
init();
std :: sort(k + 1, k + cnt + 1);
f[0][0] = 1;
//for (R int i = 1; i <= cnt; i++) cerr(k[i]);
for (R int i = 1, S = 0; i <= cnt; i++) {
S += k[i];
for (R int j = 1; j <= S; j++)
for (R int K = 1; K <= k[i] && K <= j; K++)
f[i][j] = (f[i][j] + (1LL * f[i - 1][j - K] * iep(k[i], K) *
cc(k[i] - 1, K - 1) % p * ifac[K] % p * fac[k[i]]) % p) % p;
}
LL ans = 0;
for (R int i = cnt; i <= n; i++)
ans = (ans + 1LL * fac[i] * f[cnt][i] % p) % p;//, cerr(iep(n, i));
printf("%lld\n", (ans % p + p) % p);
}

posted @ 2019-10-16 08:08  ComeIntoCalm  阅读(81)  评论(0编辑  收藏