素数路径 Prime Distance On Tree 点分治+FFT

对于这个题,没有什么好用的数学性质,那么考虑统计所有长度的路径条数

路径统计问题不难想到点分治之后统计每个点的路径条数即可

假设之前子树到根的距离集合存为B,其中B[i]表示到根距离为i的有多少条

当前子树为A,那么所有路径生成路径不拿发现符合A*B的卷积形式

而且对于一个分治块,路径长度不超过结点个数,因此规模可以降低到同阶

每次对一个子树用FFT计算统计,可以写出如下代码:

#include
#include
#include
using namespace std;
typedef long long LL;
const int Mn=200005;
const double Pi=acos(-1);
struct Edge{int to,next;}w[Mn];
int n,cnt=0,h[Mn],vst[Mn],minn,tg,s[Mn],sz,prm[Mn];
LL sum[Mn],sp[Mn],sn[Mn];
complexft[Mn],fft1[Mn],fft2[Mn];
void FFT(complexA[],int n,int ty){
	 int i,j,k,m;
	 complext0,t1;
	 for(i=0;i>=1);
	 	if(i(0,ty*Pi/m));
	 	for(i=1;i

结果无限TLE成狗。。。本地测试每个点1.6s出来。。

去膜了一下其他人的代码,发现我计算过根路径条数的姿势不够优雅。。

不妨用总共的减去各个子树内部的路径,这样对于每个子树扩展大小与子树同阶,而我的方法是与父分治块同阶,复杂度不能保证

注意这样写每条路径会被统计两次,最后要除以2

#include
#include
#include
using namespace std;
typedef long long LL;
const int Mn=200005;
const double Pi=acos(-1);
struct Edge{int to,next;}w[Mn];
int n,cnt=0,h[Mn],vst[Mn],minn,tg,s[Mn],sz,prm[Mn];
LL sum[Mn],sp[Mn],sn[Mn];
complexft[Mn],fft1[Mn],fft2[Mn];
void FFT(complexA[],int n,int ty){
	 int i,j,k,m;
	 complext0,t1;
	 for(i=0;i>=1);
	 	if(i(cos(Pi/m),ty*sin(Pi/m));
	 	for(i=1;i



你可能感兴趣的:(点分治,FFT)