zoukankan      html  css  js  c++  java
  • P3338 [ZJOI2014]力

    (color{#0066ff}{ 题目描述 })

    给出n个数qi,给出Fj的定义如下:

    (F_j = sum_{i<j}frac{q_i q_j}{(i-j)^2 }-sum_{i>j}frac{q_i q_j}{(i-j)^2 })

    令Ei=Fi/qi,求Ei.

    (color{#0066ff}{输入格式})

    第一行一个整数n。

    接下来n行每行输入一个数,第i行表示qi。

    接下来为边

    (color{#0066ff}{输出格式})

    n行,第i行输出Ei。

    与标准答案误差不超过1e-2即可。

    (color{#0066ff}{输入样例})

    5
    4006373.885184
    15375036.435759
    1717456.469144
    8514941.004912
    1410681.345880
    

    (color{#0066ff}{输出样例})

    -16838672.693
    3439.793
    7509018.566
    4595686.886
    10903040.872
    

    (color{#0066ff}{数据范围与提示})

    对于30%的数据,n≤1000。

    对于50%的数据,n≤60000。

    对于100%的数据,n≤100000,0<qi<1000000000。

    (color{#0066ff}{ 题解 })

    (q_i)除掉

    (f_i=p_i, g_i=frac{1}{i^2})

    (egin{aligned}F_i=sum_{j = 1}^{i - 1}f(j)*g(i-j)-sum_{j = i +1}^{n}f(j)*g(j-i)end{aligned})

    考虑一个卷积(egin{aligned}f_n=sum_{i = 1}^n g(i)*h(n - i) end{aligned})

    一个函数(f(i)),当做多项式,就是(x^i)的系数

    不难发现,因为(i + n - i) = n

    所以上面的卷积其实就是g和h卷起来第n项的系数!

    回到本题

    将前面的(sum)用FFT算出来,因为(j+i-j=i),因此前面的部分第i项的系数就是第i个ans

    后面的(sum)不好弄,要把j消掉,可以将后面翻转成(egin{aligned}sum_{j = i + 1}^{n}f(j)*g(n - (j - i)+1)end{aligned})

    (j + n -j+i+1=n+i+1),所以后半部分的第i个ans就是卷积的第n+i+1项(把g翻转后再卷积)

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const double pi = acos(-1);
    const int maxn = 3e5 + 10;
    double p[maxn];
    struct node {
    	double x, y;
    	node(double x = 0, double y = 0): x(x), y(y) {}
    	friend node operator + (const node &a, const node &b) { return node(a.x + b.x, a.y + b.y); }
    	friend node operator - (const node &a, const node &b) { return node(a.x - b.x, a.y - b.y); }
    	friend node operator * (const node &a, const node &b) { return node(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
    	friend node operator / (const node &a, const double &b) { return node(a.x / b, a.y / b); }
    }A[maxn], B[maxn], E[maxn], F[maxn];
    int len, n, r[maxn];
    void FFT(node *D, int flag) {
    	for(int i = 0; i < len; i++) if(i < r[i]) std::swap(D[i], D[r[i]]);
    	for(int l = 1; l < len; l <<= 1) {
    		node w0(cos(pi / l), flag * sin(pi / l));
    		for(int i = 0; i < len; i += (l << 1)) {
    			node w(1, 0), *a0 = D + i, *a1 = D + i + l;
    			for(int k = 0; k < l; k++, a0++, a1++, w = w * w0) {
    				node tmp = *a1 * w;
    				*a1 = *a0 - tmp;
    				*a0 = *a0 + tmp;
    			}
    		}
    	}
    	if(flag == -1) for(int i = 0; i < len; i++) D[i] = D[i] / len;
    }
    int main() {
    	n = in();
    	for(int i = 1; i <= n; i++) scanf("%lf", &p[i]);
    	for(int i = 1; i <= n; i++) A[i].x = p[i];
    	for(int i = 1; i <= n; i++) B[i].x = 1.0 / i / i;
    	for(len = 1; len <= n + n + 2; len <<= 1);
    	for(int i = 0; i < len; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) * (len >> 1));
    	FFT(A, 1), FFT(B, 1);
    	for(int i = 0; i < len; i++) E[i] = A[i] * B[i];
    	FFT(E, -1);
    	for(int i = 0; i < len; i++) A[i] = B[i] = node();
    	for(int i = 1; i <= n; i++) A[i].x = p[i];
    	for(int i = 1; i <= n; i++) B[i].x = 1.0 / (n - i + 1) / (n - i + 1); 
    	FFT(A, 1), FFT(B, 1);
    	for(int i = 0; i < len; i++) F[i] = A[i] * B[i];
    	FFT(F, -1);
    	for(int i = 1; i <= n; i++) printf("%.3f
    ", E[i].x - F[n + i + 1].x);
    	return 0;
    }
    
  • 相关阅读:
    BZOJ 2212/BZOJ 3702
    BZOJ 4761 Cow Navigation
    BZOJ 3209 花神的数论题
    BZOJ 4760 Hoof, Paper, Scissors
    BZOJ 3620 似乎在梦中见过的样子
    BZOJ 3940 Censoring
    BZOJ 3942 Censoring
    BZOJ 3571 画框
    BZOJ 1937 最小生成树
    BZOJ 1058 报表统计
  • 原文地址:https://www.cnblogs.com/olinr/p/10270095.html
Copyright © 2011-2022 走看看