hdu-6472 艺术台阶(微积分+多项式维护)
题意:
实际上就是求
\(\sum^{a[1]}_{i=0}\frac{1}{a[1]}\sum^{a[2]}_{j=i}\frac{1}{a[2]}\sum^{a[3]}_{k=j}\frac{1}{a[3]}\cdots(a[1]<=a[2]<=a[3]\cdots)\)
解题思路:
题目给我们的a[i]并不保证是非递减的,比如一个1 4 2的序列,所以实际上的积分是\(\frac{1}{1*4*2}\sum^{1}_{i=0}\sum^{2}_{j=i}\sum^{2}_{k=j}\)
那么我们假设处理好的每个积分上限为\(b[i]\)
以三项为例
那么把系数往前提就有
\(\frac{1}{\prod^{n}_{i=1}a[i]}\sum^{b[1]}_{i=0}\sum^{b[2]}_{j=i}\sum^{b[3]}_{k=j}\)
我们从最后一个积分往前积,一开始要维护的多项式只有一个1,\(1dk=k\),已知上下限做定积分就有
\(\frac{1}{\prod^{n}_{i=1}a[i]}\sum^{b[1]}_{i=0}\sum^{b[2]}_{j=i}(b[3]-j)\)
同理\((b[3]-j)dj=b[3]j-\frac{j^2}{2}\)
\(\frac{1}{\prod^{n}_{i=1}a[i]}\sum^{b[1]}_{i=0}b[3]i-\frac{i^2}{2}\)
这就差不多了,维护下这个多项式就行然后我把自己wa飞了
#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<ll, ll> PLL;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e5 + 7;
const ll MAXM = 2e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll quick_pow(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)
ans = (1LL * ans * a) % MOD;
a = (1LL * a * a) % MOD;
b >>= 1;
}
return ans;
}
ll mp[3005];
ll a[3005];
ll b[3005];
ll pre[3005];
int main()
{
int n;
int t;
scanf("%d", &t);
for (int i = 1; i <= 2005; i++)
pre[i] = quick_pow(i, MOD - 2);
while (t--)
{
memset(mp, 0, sizeof(mp));
scanf("%d", &n);
ll div = 1;
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
b[i] = a[i];
div *= a[i];
div %= MOD;
}
for (int i = n; i >= 2; i--)
{
if (b[i - 1] > b[i])
b[i - 1] = b[i];
}
ll now = 2;
mp[1] = 1;
for (int i = n; i >= 2; i--)
{
ll temp = 0;
for (int j = 0; j <= now - 1; j++)
{
(temp += (mp[j] * quick_pow(b[i], j)) % MOD) %= MOD;
mp[j] = -mp[j];
}
(mp[0] += temp) %= MOD;
for (int j = now; j >= 1; j--)
{
mp[j] = (pre[j] * mp[j - 1]) % MOD;
mp[j] %= MOD;
}
mp[0] = 0;
now++;
}
ll son = 0;
for (int i = 0; i <= n; i++)
{
son += ((mp[i] * quick_pow(b[1], i)) % MOD);
son %= MOD;
}
ll inv = quick_pow(div, MOD - 2);
printf("%lld\n", ((son * inv % MOD) + MOD) % MOD);
}
return 0;
}