[启发式合并 乱搞] 计蒜客 10447 立方数路径
来源:互联网 发布:黄金是怎么形成的 知乎 编辑:程序博客网 时间:2024/06/16 20:56
可以在LCA处统计答案 然后考虑向上启发式合并
怎么统计答案 注意到 质因子的个数只有30个 我们用
#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#include<cstring>#include<tr1/unordered_map>#define cl(x) memset(x,0,sizeof(x))#define pb push_backusing namespace std;using namespace std::tr1; typedef long long ll;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline int read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; else if (c==EOF) return 0; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; return 1;}inline void read(ll &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int K=729;int sum[K][K],inv[K];inline void div(int x,int *a){ for (int i=0;i<6;i++) a[i]=x%3,x/=3;}inline int com(int *a){ int ret=0; for (int i=5;~i;i--) ret=ret*3+a[i]; return ret;}inline void Pre(){ int a[6],b[6]; for (int i=0;i<K;i++){ div(i,a); for (int j=0;j<6;j++) a[j]=(3-a[j])%3; inv[i]=com(a); } for (int i=0;i<K;i++) for (int j=0;j<K;j++){ div(i,a); div(j,b); for (int k=0;k<6;k++) (a[k]+=b[k])%=3; sum[i][j]=com(a); }}inline ll Sum(ll x,ll y){ ll ret=0; int a[5],b[5]; for (int i=0;i<5;i++) a[i]=x%K,x/=K,b[i]=y%K,y/=K; for (int i=0;i<5;i++) a[i]=sum[a[i]][b[i]]; for (int i=4;~i;i--) ret=ret*K+a[i]; return ret;}inline ll Inv(ll x){ ll ret=0; int a[5]; for (int i=0;i<5;i++) a[i]=x%K,x/=K; for (int i=0;i<5;i++) a[i]=inv[a[i]]; for (int i=4;~i;i--) ret=ret*K+a[i]; return ret;}const int N=50005;struct edge{ int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}int n,m; ll Ans;ll val[N],prime[35];inline ll calc(ll x){ ll ret=0; for (int i=1;i<=30;i++){ int cnt=0; if (prime[i]) while (x%prime[i]==0) cnt++,x/=prime[i]; ret=ret*3+cnt%3; } return ret;}typedef unordered_map<ll,int> Set;typedef unordered_map<ll,int>::iterator ITER;Set _S[N],*S[N];inline int Count(Set *s,ll x){ if (s->count(x)) return (*s)[x]; return 0;}inline Set *Merge(Set *s1,Set *s2,ll tmp){ if (s1->size()<s2->size()) swap(s1,s2); for (ITER i=s2->begin();i!=s2->end();i++) Ans+=(ll)i->second*Count(s1,Sum(tmp,Inv(i->first))); for (ITER i=s2->begin();i!=s2->end();i++) (*s1)[i->first]+=i->second; return s1;}#define V G[p].vinline void dfs(int u,int fa){ val[u]=Sum(val[u],val[fa]); _S[u].clear(); _S[u][val[u]]++; S[u]=&_S[u]; ll tmp=Sum(val[u],val[fa]); for (int p=head[u];p;p=G[p].next) if (V!=fa){ dfs(V,u); S[u]=Merge(S[u],S[V],tmp); }}int main(){ int iu,iv; freopen("t.in","r",stdin); freopen("t.out","w",stdout); Pre(); while (read(n)){ read(m); for (int i=1;i<=m;i++) read(prime[i]); for (int i=1;i<=n;i++) read(val[i]),val[i]=calc(val[i]),Ans+=val[i]==0; for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum); dfs(1,0); printf("%lld\n",Ans); Ans=0; cl(head); inum=0; } return 0;}
0 0
- [启发式合并 乱搞] 计蒜客 10447 立方数路径
- 机器,立方数,长跑路径
- 启发式合并
- 并查集的启发式合并 和 路径压缩
- 并查集——启发式合并,路径压缩
- 并查集(路径压缩 && 启发式合并!!!)
- 并查集的优化---路径压缩与启发式合并
- bzoj 1438(启发式合并)
- 树上启发式合并
- BZOJ2733 永无乡 [启发式合并]
- Hdu 6133 启发式合并
- map + 启发式合并
- 树状数组+启发式合并
- 启发式合并&线段树合并&treap合并
- HDU5519 Kykneion asma (指数生成函数+快速数论变换模任意数+启发式合并思想)
- HDU5519 Kykneion asma (指数生成函数+快速数论变换模任意数+启发式合并思想)
- hdu 5997 rausen loves cakes [启发式合并+树状数组/线段数]【杂类+数据结构】
- 伸展树的启发式合并
- acm题目1001开始的代码
- PAT-B1045. 快速排序
- linux下git分支的创建
- 运用递归思想实现剪切任意文件夹
- 数据库范式——第一范式、第二范式、第三范式
- [启发式合并 乱搞] 计蒜客 10447 立方数路径
- linux stat命令三个时间详解
- 我和梁定郊一起川藏游的感慨
- ZOJ 2967Colorful Rainbows
- 继承linearLayout实现自定义布局的方法
- docker常用命令总结
- PAT 1009
- java 选择排序
- 字符串加密工具