描述node
儘管付出了種種努力,jzp仍是得過光棍節。ios
jzp很是不爽,但也無能爲力,只可以哀嘆起來他的命運。他想到了一位長者的人生經驗:「人的一輩子,不光要靠自我奮鬥,也要考慮歷史的進程」。數組
他終於明白本身只是時運不濟,因此又繼續開始努力。終於在聖誕節當天把到了妹子。app
jzp今後過上了快樂的現充生活,在聖誕節當天,他還和妹子玩起了有趣的遊戲:spa
jzp的家裏有一棵很是大的聖誕樹,能夠當作是一個n個點的無向聯通無環圖。每一個點上都有一個正整數,JZP和妹子每次都會選擇樹上的一條路徑,code
這條路徑的權值被定義爲路徑上全部點上數的最大公約數,JZP能夠獲得這個權值的分數。遊戲
JZP玩了一下子有點膩了,他想知道對於每種可能的權值x,權值爲x的不一樣路徑的數量(a到b的路徑和b到a的路徑算做一種,a到a自身也算做一條路徑。)進程
解題報告:
用時2h30min,N TLE
這題不難,直接暴力點分,複雜度能夠證實是對的,由於從一個點下去,gcd只有能夠是它的約數,因此是\(\sqrt n\)的,因此直接去重以後兩重循環枚舉,複雜度是\(O(n)\)的,因此複雜度是對的。可是本人太渣,點分均可以寫錯,找重心的數組一直沒清空(那麼竟然是0.7s是怎麼回事?)而後一交就TLE,還覺得是常數太大,就一直在壓,浪費了許久,寫了兩個代碼,一個是全部方案-不合法的,另外一個是用vector維護已經處理過的子樹的gcd,處理完當前子樹後,在處理另外一個子樹直接用當前子樹的每個gcd和vector裏的元素匹配.get
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #define RG register #define il inline #define iter iterator #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; const int N=1e5+5; int n,val[N],head[N],num=0,nxt[N<<1],to[N<<1],sum; void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;} bool vis[N];int sz[N],root=0,son[N]={N}; il int gi(){ RG int str=0;RG char ch=getchar(); while(ch>'9' || ch<'0')ch=getchar(); while(ch>='0' && ch<='9') str=(str<<1)+(str<<3)+ch-48,ch=getchar(); return str; } il void getroot(int x,int last){ int u;sz[x]=1;son[x]=0; for(int i=head[x];i;i=nxt[i]){ u=to[i];if(u==last || vis[u])continue; getroot(u,x); sz[x]+=sz[u];son[x]=Max(son[x],sz[u]); } son[x]=Max(son[x],sum-sz[x]); if(son[x]<son[root])root=x; } il int gcd(int x,int y){ int c;while(x%y){c=y;y=x%y;x=c;} return y; } vector<int>q,s;ll t[N],ton[N]; void count(int x){ int szz=q.size(),gc; for(int i=0;i<szz;i++){ gc=gcd(q[i],x); t[gc]+=ton[q[i]]; } } int app[N]; il void calc(int x,int last,int g){ int u; t[g]++;count(g); if(!app[g])s.push_back(g);app[g]++; for(int i=head[x];i;i=nxt[i]){ u=to[i];if(u==last || vis[u])continue; if(g!=1)calc(u,x,gcd(val[u],g)); else calc(u,x,1); } } il void solve(int x){ int u,szz; for(int i=head[x];i;i=nxt[i]){ u=to[i];if(vis[u])continue; calc(u,x,gcd(val[u],val[x])); szz=s.size(); for(int j=0;j<szz;j++){ if(!ton[s[j]])q.push_back(s[j]); ton[s[j]]+=app[s[j]];app[s[j]]=0; } s.clear(); }szz=q.size(); for(int i=0;i<szz;i++)ton[q[i]]=0; q.clear(); } il void dfs(int x){ int u;vis[x]=true;solve(x); for(int i=head[x];i;i=nxt[i]){ u=to[i];if(vis[u])continue; root=0;sum=sz[u];getroot(u,x); dfs(root); } } void work() { int x,y,lim=0; scanf("%d",&n); for(int i=1;i<=n;i++){ val[i]=gi(); lim=Max(lim,val[i]); t[val[i]]++; } for(int i=1;i<n;i++){ x=gi();y=gi(); link(x,y);link(y,x); } sum=n;root=0;getroot(1,1); dfs(root); for(int i=1;i<=lim;i++) if(t[i])printf("%d %lld\n",i,t[i]); } int main() { work(); return 0; }
再是原來寫的,清空數組後也能過string
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #define RG register #define il inline #define iter iterator #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; const int N=1e5+5; int n,val[N],head[N],num=0,nxt[N<<1],to[N<<1],sum; void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;} bool vis[N];int sz[N],root=0,son[N]={N}; il int gi(){ RG int str=0;RG char ch=getchar(); while(ch>'9' || ch<'0')ch=getchar(); while(ch>='0' && ch<='9') str=(str<<1)+(str<<3)+ch-48,ch=getchar(); return str; } il void getroot(int x,int last){ int u;sz[x]=1;son[x]=0; for(int i=head[x];i;i=nxt[i]){ u=to[i];if(u==last || vis[u])continue; getroot(u,x); sz[x]+=sz[u];son[x]=Max(son[x],sz[u]); } son[x]=Max(son[x],sum-sz[x]); if(son[x]<son[root])root=x; } il int gcd(int x,int y){ int c;while(x%y){c=y;y=x%y;x=c;} return y; } struct node{ int x;ll cnt; bool operator <(const node &Pr)const{return x<Pr.x;} }q[N]; int top=0;bool flag=false; il void calc(int x,int last,int g){ int u; if(g==1 && flag){q[++top].x=1;q[top].cnt=sz[x];return ;} if(top && q[top].x==g)q[top].cnt++; else q[++top].x=g,q[top].cnt=1; for(int i=head[x];i;i=nxt[i]){ u=to[i];if(u==last || vis[u])continue; if(g!=1)calc(u,x,gcd(val[u],g)); else calc(u,x,1); } } ll t[N]; il void solve(int x,int op,int sta){ top=0;calc(x,x,sta); int Yut=top;top=1; sort(q+1,q+Yut+1); RG int i,j; for(i=2;i<=Yut;i++){ if(q[i].x==q[top].x)q[top].cnt+=q[i].cnt; else q[++top]=q[i]; } int tmp; for(i=1;i<=top;i++){ t[q[i].x]+=q[i].cnt*(q[i].cnt-1)*op>>1; for(j=i+1;j<=top;j++){ tmp=gcd(q[i].x,q[j].x); t[tmp]+=q[i].cnt*q[j].cnt*op; } } } il void dfs(int x){ int u;vis[x]=true; flag=false;solve(x,1,val[x]); for(int i=head[x];i;i=nxt[i]){ u=to[i];if(vis[u])continue; root=0;sum=sz[u];getroot(u,x); flag=true;solve(u,-1,gcd(val[x],val[u])); dfs(root); } } void work() { int x,y,lim=0; scanf("%d",&n); for(int i=1;i<=n;i++){ val[i]=gi(); lim=Max(lim,val[i]); t[val[i]]++; } for(int i=1;i<n;i++){ x=gi();y=gi(); link(x,y);link(y,x); } sum=n;root=0;getroot(1,1); dfs(root); for(int i=1;i<=lim;i++) if(t[i])printf("%d %lld\n",i,t[i]); } int main() { work(); return 0; }