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));
    }
    
  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/daklqw/p/11638392.html
Copyright © 2011-2022 走看看