# [BZOJ2655]calc

### [BZOJ2655]calc

#### 试题描述

$a_1, \cdots , a_n$ 都是 $[1,A]$ 中的整数。

$a_1, \cdots , a_n$ 互不相等。

#### 输入示例

9 7 10007


#### 输出示例

3611


#### 数据规模及约定

$0: A \le 10,n \le 10$

$1 \sim 3: A \le 1000,n \le20$.

$4 \sim 9: A \le 10^9,n \le 20$

$10 \sim 19: A \le 10^9,n \le 500$

#### 题解

$f(i, j)$ 表示 $[1, i]$ 中的数取 $j$ 个的所有方案的乘积总和，那么转移如下

$f(i, j) = f(i-1, j-1) \cdot i \cdot j + f(i-1, j)$

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)

int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}

#define maxn 510
#define LL long long

int Arrange, n, MOD, f[maxn*3][maxn], inv[maxn*3];

int X[maxn<<1], Y[maxn<<1];
int GetPoly(int N, int x) {
int ans = 0;
rep(i, 1, N) {
int sum = Y[i];
rep(j, 1, N) if(i != j) {
sum = (LL)sum * (x - X[j]) % MOD * inv[abs(X[i]-X[j])] % MOD;
if(sum < 0) sum += MOD;
if(X[i] < X[j] && sum) sum = MOD - sum;
}
ans += sum;
if(ans >= MOD) ans -= MOD;
}
return ans;
}

int main() {

int lim = min(Arrange, n * 3 + 1);
rep(i, 0, lim) f[i][0] = 1;
rep(i, 1, lim) rep(j, 1, n) {
f[i][j] = (LL)f[i-1][j-1] * i % MOD * j % MOD + f[i-1][j];
if(f[i][j] >= MOD) f[i][j] -= MOD;
}
if(Arrange == lim) return printf("%d\n", f[lim][n]), 0;

rep(i, n + 1, lim) X[i-n] = i, Y[i-n] = f[i][n];
inv[1] = 1;
rep(i, 2, lim) inv[i] = (LL)(MOD - MOD / i) * inv[MOD%i] % MOD;
printf("%d\n", GetPoly(n << 1 | 1, Arrange));

return 0;
}

posted @ 2018-03-05 19:46  xjr01  阅读(304)  评论(0编辑  收藏