[ZJOI2014] 力

题意:给定 ({q_i}),求

[E_i = sum_{i<j}{frac{q_j}{(j-i)^2}} - sum_{i>j}{frac{q_j}{(j-i)^2}} ]

Solution: 我们令

[p_i = frac{1}{(j-i)^2} ]

那么很容易将(E_i)处理为卷积形式

[E_i = sum_{i<j}{p_{j-i}q_j} - sum_{i>j}{p_{i-j}q_j} ]

可以暴力地把两边分开处理,不需要的区域直接置为(0),对于下标出现负数的暴力加上一个(n)即可。最终我们将答案转化为

[E_i = sum_{i<j}{p_{j-i}q'_{n-i-1}} - sum_{i>j}{p_{i-j}q_j} ]

其中 (q')(q)的翻转序列,即 (q'_i=q_{n-i-1})

之所以在这个算式里仍然需要考虑负数下标,是因为我们在做卷积的时候无法对 (i<j)(i>j) 这样的约束进行满足,因此我们将 (p) 序列整体平移一个 (n) 即可。

poly p,q;

int main() {
	int n;
	scanf("%d",&n);
	q.read(n-1);
	p.c.resize(n+n);
	for(int i=0;i<=n;i++) p.c[i]=0;
	for(int i=1;i<n;i++) p.c[n+i]=1.0/((double)i*(double)i);
	poly A=p*q;
	reverse(q.c.begin(),q.c.end());
	poly B=p*q;
	for(int i=0;i<n;i++) {
		printf("%.3lf
",-B.c[2*n-i-1]+A.c[n+i]);
	}
}

当然很容易发现这样做毫无必要。既然我们已经对下标为负数的情况做了处理,不妨顺便把它利用上。

poly p,q;

int main() {
	int n;
	scanf("%d",&n);
	q.read(n-1);
	p.c.resize(n+n);
	for(int i=1;i<n;i++)
		p.c[n+i]=1.0/((double)i*(double)i),
		p.c[n-i]=-1.0/((double)i*(double)i);
	poly A=p*q;
	for(int i=0;i<n;i++) {
		printf("%.3lf
",A.c[n+i]);
	}
}
原文地址:https://www.cnblogs.com/mollnn/p/11631933.html