BSOJ5216题解

比较简单的一道题。

需要满足 \(a_u^2+Aa_ua_v+Ba_v^2\equiv 0\pmod p\)

如果枚举 \(v\) 的话,那么相当于是 \(a_u\) 需要满足一个二次方程 \(x^2+(Aa_v)\times x+Ba_v^2\equiv 0\pmod p\)

所以可以先解 \(a_v\) 对应的方程。\(p\) 是质数所以只可能有两个解。

然后写一个 dfs序+hash+差分就可以了。

复杂度 \(O(n\log^2p)\)

但是你会被卡常

回头看看:\(\Delta=(Aa_v)^2-4\times Ba_v^2=a_v^2\times(A^2-4\times B)\)

所以只需要求 \(A^2-4\times B\) 的二次剩余即可。

#pragma GCC optimize(2)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#pragma GCC optimize(3,"Ofast","inline")
#include<unordered_map>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<ctime>
typedef __uint128_t LL;
typedef unsigned long long ull;
const int M=1e5+5;
std::unordered_map<ull,int>CB;
int n,edg,dfc,h[M];ull ans,A,B,delta,mod,a[M],val[M];
struct Pair{
	bool opt;ull V;
};std::vector<Pair>id[M];
struct Edge{
	int v,nx;
}e[M];
inline void AddEdge(const int&u,const int&v){
	e[++edg]=(Edge){v,h[u]};h[u]=edg;
}
inline ull pow(ull a,ull b=mod-2){
	ull ans(1);for(;b;b>>=1,a=(LL)a*a%mod)if(b&1)ans=(LL)ans*a%mod;return ans;
}
inline ull div2(const ull&n){
	return n&1?n+mod>>1:n>>1;
}
inline ull mo(const ull&n){
	return n>=mod?n-mod:n;
}
namespace Cipolla{
	ull i2;
	struct cpx{
		ull x,y;
		cpx(const ull&x=0,const ull&y=0):x(x),y(y){}
		inline cpx operator*(const cpx&it)const{
			return cpx((ull)(((LL)x*it.x+(LL)y*it.y%mod*i2)%mod),(ull)(((LL)x*it.y+(LL)y*it.x)%mod));
		}
	};
	inline cpx pow(cpx a,ull b){
		cpx ans(1,0);for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;return ans;
	}
	inline bool check(const ull&n){
		return ::pow(n,mod-1>>1)==1;
	}
	inline ull Solve(const ull&n){
		if(!n)return 0;if(!check(n))return-1;
		ull a=1;do a=(LL)rand()*rand()*rand()*rand()%mod;while(check(i2=(ull)(((LL)a*a+mod-n)%mod)));
		return pow(cpx(a,1),mod+1>>1).x;
	}
}
inline void DFS(const int&u){
	const int L=++dfc;for(int E=h[u];E;E=e[E].nx)DFS(e[E].v);val[L]=a[u];
	const int R=dfc;const ull&B=(ull)((LL)::A*a[u]%mod);
	const ull&delta=(LL)a[u]*::delta%mod;if(a[u]&&!~::delta)return;
	const ull&X1=mo(div2(mod-B+delta)),&X2=mo(div2(mod-B+mod-delta));
	id[L].push_back((Pair){false,X1}),id[R].push_back((Pair){true,X1});
	if(X1^X2)id[L].push_back((Pair){false,X2}),id[R].push_back((Pair){true,X2});
}
inline ull read(){
	ull n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
signed main(){
	srand(time(NULL));srand(rand()*rand());
	n=read();mod=read();A=read();B=read();
	delta=Cipolla::Solve((ull)(((LL)A*A+mod*4-B*4)%mod));
	for(int i=1;i<=n;++i)a[i]=read();for(int i=2;i<=n;++i)AddEdge(read(),i);DFS(1);
	for(int i=1;i<=n;++i){
		++CB[val[i]];for(Pair&x:id[i])if(CB.find(x.V)!=CB.end())if(x.opt)ans+=CB[x.V];else ans-=CB[x.V];
	}
	printf("%lld",ans);
}
posted @ 2022-05-02 20:19  Prean  阅读(26)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};