首页 > 其他分享 >H. Needle[FFT]或bitset

H. Needle[FFT]或bitset

时间:2023-08-27 21:35:35浏览次数:36  
标签:FFT 30000 int comp Needle cin bitset include

Problem - H - Codeforces

题意是给三面墙(简化为一条轴),然后给墙上的洞(简化成点),问多少直线可以从第一面墙穿出第三面墙。

要使三点共线,那么(b-a)=(c-b)即(a+c)=2*b

由于n是1e5所以O(n2)会超时。有两种做法

1.本题的任意两数相加的步骤类似多项式乘法,我们把a,c看成两个多项式的系数,然后用FFT,最后计算下b里每个元素*2指数的系数之和即可。注意数组的数可能有负数,整体+3e4即可。

查看代码

#pragma GCC optimize(2)
#include<iostream>
#include<cmath>
#include<complex>
#define int long long
using namespace std;
typedef complex<double> comp; 
const comp I=comp(0, 1);
const double PI = acos(-1);
const int MAXN=500005;
comp d[150005],e[150005],f[150005];
int ans=0,a,c,b[150005];
int rev[MAXN * 3];
void fft(comp F[], int N, int sgn = 1)
{
	int bit = __lg(N);
	for (int i = 0; i < N; ++i)
	{
		rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
		if (i < rev[i])
			swap(F[i], F[rev[i]]);
	}
	for (int l = 1; l < N; l <<= 1) 
	{
		comp step = exp(sgn * PI / l * I);
		for (int i = 0; i < N; i += l * 2) 
		{
			comp cur(1, 0);
			for (int k = i; k < i + l; ++k)
			{
				comp g = F[k], h = F[k + l] * cur;
				F[k] = g + h, F[k + l] = g - h;
				cur *= step;
			}
		}
	}
	if(sgn==-1)
	{
		for(int i=0;i<N;i++)
		F[i]/=N;
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int aa,bb,cv,zx=0,cx=0;
	cin>>aa;
	for(int i=1;i<=aa;i++)
	{
		cin>>a;
		a+=30000;
		zx=max(a,zx);
		e[a]+=1;
	}
	cin>>bb;
	for(int i=1;i<=bb;i++)
	{
		cin>>b[i];
		b[i]+=30000;
	}
	cin>>cv;
	for(int i=1;i<=cv;i++)
	{
		cin>>c;
		c+=30000;
		cx=max(cx,c);
		f[c]+=1;
	}
	int A=1<<__lg(cx+zx+1)+1;
	fft(e,A,1);
	fft(f,A,1);
	for(int i=0;i<A;i++)
		d[i]=e[i]*f[i];
	fft(d,A,-1);
	for(int i=1;i<=bb;i++)
		ans+=((d[b[i]*2].real())+0.1);//FFT+0.1避免浮点数的问题 
	cout<<ans;
	return 0;
}

2.用bitset解决。在CF看到的解法,比第一种简单且易于实现。

(b-a)=(c-b),-> (-a+b)=(c-b)

那么我们将其中另一条反转下。因为b所在的点仅仅是0,那么反转后与运算为1的数目就是0位置b点可通过的方式数。

那么b的-1这个怎么找呢?从原图我们可以看到(0,-2)是符合条件的。 (-a+b)=(c-b)得知,需要一个+b一个-b,那么此时对准的孔洞只有一个

那么用bitset实现即可。在CF上第二种时间大概是第一种的10倍。

查看代码
 //https://codeforces.com/gym/102920/problem/H
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<iostream>
#include<bitset>
#define int long long
using namespace std;
bitset<60005>a,c;
int b[50005],n,m,x;
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
		a[x+30000]=1;
	}
	cin>>m;
	for(int i=1;i<=m;i++)cin>>b[i];
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
		c[30000-x]=1;
	}
	int ans=0;
	for(int i=1;i<=m;i++)
	{
		if(b[i]>0)
		ans+=((a>>b[i])&(c<<b[i])).count();
		else ans+=((a<<(-b[i]))&(c>>(-b[i]))).count();
	}
	cout<<ans;
	return 0;
}

标签:FFT,30000,int,comp,Needle,cin,bitset,include
From: https://www.cnblogs.com/qbning/p/17660895.html

相关文章

  • Codeforces Round 889 (Div. 1) B. Earn or Unlock(dp,bitset)
    题目链接:https://codeforces.com/problemset/problem/1854/B 题目大致题意: 有n张卡牌从上到下堆叠,每张卡片有锁或不锁俩种状态,一开始第一张是不锁的;对最上面的卡牌,如果他是不锁的状态,那么可以进行俩种操作:1:从上到下,将v张被锁的卡牌解锁;2:获取v点能量现在求能获得的最大的......
  • bitset优化01可行背包
    例题传送门:『STA-R3』Aulvwc先讲bitset用法:1,基础下标:\(5~4~3~2~1~0\)数字:\(0~0~0~0~1~0\)\(bitset\)<\(n\)>\(s\)表示一个\(n\)位的二进制数,空间复杂度:\(O(\frac{n}{32})\),可见其非常优秀因为其跟二进制有关,所以可以使用\(\&,|,\land\)对两个位数相同的\(bitset\)执行按......
  • AOJ0525(bitset, 穷举)
    这题有3点要注意:1.thefliporderisnotrelatedtoresult.2.whywecansimplycounttomaximumofnumbereachcolumn?Imagineonlymanipulatetherow,itiseasytounderstandthatitisunnecessarytoflipthemratherthancountthemaximumside.3.Aga......
  • 快速傅里叶变换(FFT)基础
    本文是对FFT和NTT原理及实现的介绍,包含所有必要的证明.阅读本文需要具备一点基本的代数知识.给定\(n\)次多项式\(F(x)\)和\(m\)次多项式\(G(x)\),现在要求它们的卷积\(H(x)=F(x)G(x)\).朴素的暴力实现复杂度为\(O(nm)\),而FFT或NTT可以(在一定的精度范围内或模意......
  • FFT 小记
    目录复数单位复数根PolyFFTEnd参考资料由于懒,所以没图。写得时候有点抽风,可能有typo,望指出。复数复数表述为\(a+b\timesi\),其中\(i\)是复数单位\(\sqrt{-1}\),同时由此可得\(i^2=-1\)。称\(a\)是实部(下文简称real),\(b\)是虚部(简称imag)。对于一个实数,其real等于其......
  • m基于FFT傅里叶变换的256QAM基带信号频偏估计和补偿FPGA实现,含testbench和matlab星座
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,并使用matlab2022a对结果进行星座图的显示:     频偏基带256qam信号和频偏补偿后的256qam基带信号使用matlab显示星座图,结果如下:   2.算法涉及理论知识概要         FFT傅里叶变换是一种高效的......
  • 基于FFT傅里叶变换的64QAM基带信号频偏估计和补偿算法FPGA实现,包含testbench和matlab
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,并使用matlab2022a对结果进行星座图的显示:    将FPGA的频偏基带QPSK信号和频偏补偿后的QPSK基带信号使用matlab显示星座图,结果如下:   2.算法涉及理论知识概要        FFT傅里叶变换是一种高效的......
  • 基于FFT傅里叶变换的16QAM基带信号频偏估计和补偿算法FPGA实现,包含testbench和matlab
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,并使用matlab2022a对结果进行星座图的显示:   将FPGA的频偏基带QPSK信号和频偏补偿后的QPSK基带信号使用matlab显示星座图,结果如下:   2.算法涉及理论知识概要       FFT傅里叶变换是一种高效的频谱分析......
  • 【数据结构】bitset用法
    bitset用法bitset可以说是一个多位二进制数,每八位占用一个字节,因为支持基本的位运算,所以可用于状态压缩,n位bitset执行一次位运算的时间复杂度可视为n/32.输出只能用cout1.构造:inta=5;stringb="1011";charc[4]={'1','0','1','0'};bitset<10>s1(string("1001&qu......
  • Matlab的信号频谱分析——FFT变换
    Matlab的信号频谱分析——FFT变换Matlab的信号频谱分析FFT是离散傅立叶变换的快速算法,可以将一个时域信号变换到频域。有些信号在时域上是很难看出什么特征的。但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱提取出......