花了2d打磨出来的题目,觉得很有意思。
先讲点无关的,这道题有两版,但都是对要求的量进行改动。
1.第一次要求的是y属性为a与y属性为b的两个节点的路径权值之和,对于要求的这个量,我们设v[i]为i到根节点的权值之和。那么我们先对a,b进行质因数分解,设dcg为a,b分解质因数后最长公共前缀的乘积,那么答案就是v[a]+v[b]-2*v[dcg]。
但可能会有人问wuhupai为什么不用这版,那是因为我发现了一个很有意思的性质:
y属性为a的这个点到根节点的路径权值和是a的最大质因子-1。解释起来也很简单:路上的权值全部都消掉了(觉得不理解可以手模一下),于是我想用这个性质搞点事情。于是与空气斗智斗勇3h,连续想出了5个时间复杂度能过的暴力,然后我发现要卡掉log n 的暴力要达到2^1e9也就是约3e8位的数,这肯定是不行的,于是今天早上灵光一闪,想出了这个题。
这道题的突破口就是y属性为a的这个点到根节点的路径权值和是a的最大质因子-1这个性质。我们只要能知道a的最大质因子就可以了,但是分解质因数的复杂度是O(n)的,1e7*1e7显然不能让我们通过此题,于是我们可以通过构造trie pi树的方式来用le7的时间预处理出1-1e7内所有数的最大质因子,然后边读入边取max就行了
#include<bits/stdc++.h>
using namespace std;
bool vis[10000005];
long long n,x,maxx=-1,len=0,num[5000000],v[10000005];
inline long long read(){
char c=getchar();
long long x=0,f=1;
while(c<48){if(c=='-')f=-1;c=getchar();}
while(c>47)x=(x*10)+(c^48),c=getchar();
return x*f;
}
void solve(){
for(long long i=2;i<=10000000;i++){
if(vis[i]==false){
len++;
num[len]=i;
}
for(long long j=1;j<=len&&i*num[j]<=10000000;j++){
vis[i*num[j]]=true;
if(i%num[j]==0) break;
}
}
}
void dfs(long long from,long long sum){
v[sum]=num[from];
for(long long i=from;i<=len&&sum*num[i]<=10000000;i++){
dfs(i,sum*num[i]);
}
}
int main(){
solve();
dfs(1,1);
v[1]=1;
n=read();
for(long long i=1;i<=n;i++){
x=read();
maxx=max(maxx,v[x]);
}
cout<<maxx-1;
return 0;
}
标签:U329011,trie,题解,long,1e7,权值,pi,节点
From: https://www.cnblogs.com/wuhupai/p/18036311