今天再次迎来了我们的例行考试。
T1:
首先我们考虑那些点是可以共存的,我们可以枚举一个质数做他们的gcd,然后把这些点放在一张图里求直径。
所以我们要做的就是把这些点的值分解质因数,对每个质因数挂一个链,代表有那些点包含这些质因数。然后我们枚举质因数,把这条链上的点放进图里求直径即可。由于质因数最多log个,所以复杂度nlogn。
然而分解质因数怎么做呢?10w个数,1e9的范围,暴力sqrt的分解肯定过不去,我们需要pollard rho。
然而考场上我想:pollard rho可能被卡(我才不告诉你我不会写pollard rho呢),暴力分解又过不去。况且暴力分解在最差情况下连5000都过不去,我还不如敲个n^2log的暴力呢,然后就敲了一个裸暴力进去。
结果正解就是sqrt的暴力分解,很多人都这样A了。也就是说,我们1e10的计算量信仰跑过了。行吧,我也没什么可说的了。
这道题目告诉我们即使再绝望也不要放弃骗分......
(感觉此题堪比以后要给高一考的4e8信仰背包,然而这次却并没有我那么良心的验题人)
考场15分代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define debug cout 6 using namespace std; 7 const int maxn=1e5+1e2; 8 9 int in[maxn]; 10 int s[maxn],t[maxn<<1],nxt[maxn<<1]; 11 int val[maxn],dis[maxn]; 12 int ans; 13 14 inline int gcd(int a,int b) { 15 if( ! ( a && b ) ) return a | b; 16 register int t; 17 while( t = a % b ) 18 a = b , b = t; 19 return b; 20 } 21 22 inline void addedge(int from,int to) { 23 static int cnt = 0; 24 t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt; 25 } 26 inline void dfs(int pos,int fa) { 27 ans = max( ans , dis[pos] ); 28 for(int at=s[pos];at;at=nxt[at]) 29 if( t[at] != fa ) { 30 int g = gcd(val[pos],in[t[at]]); 31 if( g != 1 ) { 32 dis[t[at]] = dis[pos] + 1 , val[t[at]] = g; 33 dfs(t[at],pos); 34 } 35 } 36 } 37 38 int main() { 39 static int n; 40 scanf("%d",&n); 41 for(int i=1,a,b;i<n;i++) { 42 scanf("%d%d",&a,&b); 43 addedge(a,b) , addedge(b,a); 44 } 45 for(int i=1;i<=n;i++) 46 scanf("%d",in+i); 47 for(int i=1;i<=n;i++) { 48 val[i] = in[i] , dis[i] = 1; 49 dfs(i,-1); 50 } 51 52 printf("%d\n",ans); 53 54 return 0; 55 }