zoukankan      html  css  js  c++  java
  • 【集训队作业2018】不可名状

    现在有用的只有 CU, CR。QR只能用一次,说明我们要用确定性的做法,而不能依赖于期望。

    记答案为 (c=omega_n^b)。和答案有关的操作只有 CU,QR返回值只和下标有关,说明需要让只有第 (b) 位有值。但是如何把值转换为下标?

    根据DFT的经验,或许我们可以构造出 (fleft(x ight) = x^b) 的点值序列,然后做一遍IDFT,这样就可以把值序列转换为单个下标了。

    这也是看到这道题容易想到的一个做法。

    现在的问题就是构造出点值序列,然后还有IDFT。因为有 ACR 操作,直接套IDFT定义式,那么只要构造出点值序列就能很方便地骗到 (62) 分了。

    将函数代入DFT矩阵,容易发现DFT后的序列为 (a_i = omega_n^{ib} = left(omega_n^a ight)^i = c^i),也就是我们需要让 (a_i = c^i)

    这个很好办,就是先用CR使每一位都为 (1),然后调用 CU(i, 1 << i)

    如何用 CR 使每一位都为 (1) ?套用我们现有的 FWT 矩阵,对于集合幂级数 (f(x) = x^emptyset) FWT的结果就是 (widehat{f}(x) = sum_{S in U} x^S)。所以用 【UTR #3】量子破碎 提到的矩阵就可以了:

    [A = left[ egin{matrix} frac{1}{sqrt{2}} & frac{1}{sqrt{2}} \ frac{1}{sqrt{2}} & -frac{1}{sqrt{2}} end{matrix} ight] ]

    虽然有 (left(frac{1}{sqrt{2}} ight)^n) 的常数差异,但对答案没影响。

    现在需要考虑 IDFT。考虑直接FFT。那么首先要 bitreverse。这很简单,我们把上面的 CU(i, 1 << i) 改为 CU(i, 1 << 15 - i),那么每一位都是 bitreverse 后的结果了。

    现在考虑 FFT 做 IDFT 的代码(代码随便打的)

    for (int mid = 1; mid != lim; mid <<= 1) {
    	const double deg = PI / mid;
    	const complex wn(cos(deg), -sin(deg));
    	for (int k = 0; k != lim; k += mid << 1) {
    		complex w(1, 0);
    		for (int l = 0; l != mid; ++l, w = w * wn) {
    			complex x = A[l + k], y = A[l + k + mid] * w;
    			A[l + k] = x + y;
    			A[l + k + mid] = x - y;
    		}
    	}
    }
    

    容易发现,实际上这个 FFT 做了两步:

    1. 对于所有第 (i) 位为 (1)(j),都乘上 (omega_{2^{i+1}}^{j} = omega_{2^{i+1}}^{j pmod {2^{i+1}}})
    2. 对于所有第 (i) 位为 (1)(j),用CR调用FWT矩阵,也就是 (l = x + y, r = x - y)

    第二步显然在这一层过后调用一次 CR(i, i, FWT) 即可。

    第一步的构造方法和我们构造点值序列类似,也是按位乘上去。只要对于每一个 (j < i),取矩阵

    [A = left[ egin{matrix} 1 & 0\ 0 & omega_{2^{i+1}}^{2^j} end{matrix} ight] ]

    显然是个酉矩阵。

    然后需要第 (j) 位也有才能乘上,所以需要调用 CR(j, i, IDFT)

    然后,QR一次然后直接返回即可。就这样做完了这道题。

    询问复杂度 (O(n ^ 2)),可以通过此题。

    这道题咕了好久天,我连FFT都不会了/px,调了好久/px

    还是冷静思考这个方法有用

    #include <bits/stdc++.h>
    #include "unnamable.h"
    
    typedef std::complex<double> C;
    
    const C is2(1 / sqrtl(2), 0);
    C fwt[2][2] = {
    	{is2, is2},
    	{is2, -is2}
    } ;
    C fft[2][2];
    const double PI = acosl(-1);
    const int MN = 16;
    C SOL(int typ) {
    	INI(MN);
    	for (int i = 0; i != MN; ++i)
    		CR(i, i, fwt);
    	for (int i = 0; i != MN; ++i)
    		CU(i, 1 << MN - 1 - i);
    	fft[0][0] = C(1, 0);
    	const int U = 1 << MN;
    	for (int i = 0; i != MN; ++i) {
    		const int mid = 1 << i;
    		const double dwn = PI / mid;
    		for (int j = 0; j < i; ++j) {
    			double deg = dwn * (1 << j);
    			fft[1][1] = C(cosl(deg), -sinl(deg));
    			CR(j, i, fft);
    		}
    		CR(i, i, fwt);
    	}
    	int ans = QR();
    	double deg = PI * 2 / (1 << MN) * ans;
    	return C(cosl(deg), sinl(deg));
    }
    
  • 相关阅读:
    iPhone/iOS图片相关(读取、保存、绘制、其它相关)
    NData转化
    UIScrollView小记
    ios学习--结合UIImageView实现图片的移动和缩放
    iphone UIScrollView缩放
    在scrollview中双击定点放大的代码
    IOS 程序内部切换语言 的一种方法
    SAP Hybris Discount group,折扣组,折扣记录,用户组几组概念的关联
    Hybris产品主数据的价格折扣维护
    Hybris订单价格的折扣维护
  • 原文地址:https://www.cnblogs.com/daklqw/p/11638392.html
Copyright © 2011-2022 走看看