http://acm.bnu.edu.cn/v3/problem_show.php?pid=52733
【题意】
- 给定一棵树,这棵树每个点都有一个点权,标号从0开始,0是根结点
- 修改操作:
SEED 1 13
把结点1的点权乘上13
- 查询操作:
RAND 1
查询结点1为根的子树所有结点权的总乘积,以及这个总乘积有多少个因子
- 题目保证结果的质因子最大为13
【思路】
- 质因子最大为13,那么我们可以枚举质因子2 3 5 7 11 13,共6个
- 只要我们知道子树乘积这六个质因子的个数,我们就能算出子树的总乘积为2^p1*3^p2*5^p3*7^p4*11^p5*13^p6,而且这个数共有(p1+1)*(p2+1)*(p3+1)*(p4+1)*(p5+1)*(p6+1)个因子
- 我们可以为每个质因子维护一个树状数组,统计因子个数和
【AC】
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 const int maxn=1e5+2;; 6 const int maxm=2*maxn; 7 const ll mod=1e9+7; 8 int n; 9 struct edge 10 { 11 int to; 12 int nxt; 13 }e[maxm]; 14 int head[maxn]; 15 int tot; 16 int l[maxn],r[maxn]; 17 int cid; 18 ll tree[7][maxm]; 19 int p[7]; 20 ll fpow(ll x,ll n) 21 { 22 ll res=1; 23 while(n) 24 { 25 if(n&1) res=(res*x)%mod; 26 x=(x*x)%mod; 27 n>>=1; 28 } 29 return res; 30 } 31 int lowbit(int x) 32 { 33 return x&(-x); 34 } 35 36 void add(int i,int k,int cnt) 37 { 38 while(k<=cid) 39 { 40 tree[i][k]+=cnt; 41 k+=lowbit(k); 42 } 43 } 44 ll query(int i,int k) 45 { 46 int res=1; 47 while(k) 48 { 49 res+=tree[i][k]; 50 k-=lowbit(k); 51 } 52 return res; 53 } 54 void init() 55 { 56 memset(head,-1,sizeof(head)); 57 tot=0; 58 cid=0; 59 memset(tree,0,sizeof(tree)); 60 } 61 void addedge(int u,int v) 62 { 63 e[tot].to=v; 64 e[tot].nxt=head[u]; 65 head[u]=tot++; 66 } 67 void dfs(int u,int pa) 68 { 69 l[u]=++cid; 70 for(int i=head[u];i!=-1;i=e[i].nxt) 71 { 72 int v=e[i].to; 73 if(v==pa) continue; 74 dfs(v,u); 75 } 76 r[u]=++cid; 77 } 78 79 void update(int i,ll x) 80 { 81 for(int j=1;j<=6;j++) 82 { 83 int cnt=0; 84 while(x%p[j]==0) 85 { 86 cnt++; 87 x/=p[j]; 88 } 89 add(j,l[i],cnt); 90 } 91 } 92 int main() 93 { 94 p[1]=2,p[2]=3,p[3]=5,p[4]=7,p[5]=11,p[6]=13; 95 while(~scanf("%d",&n)) 96 { 97 init(); 98 int u,v; 99 for(int i=1;i<=n-1;i++) 100 { 101 scanf("%d%d",&u,&v); 102 u++;v++; 103 addedge(u,v); 104 addedge(v,u); 105 } 106 dfs(1,-1); 107 for(int i=1;i<=n;i++) 108 { 109 ll x; 110 scanf("%I64d",&x); 111 update(i,x); 112 } 113 int q; 114 scanf("%d",&q); 115 char str[10]; 116 while(q--) 117 { 118 scanf("%s",str); 119 if(str[0]==‘R‘) 120 { 121 int x; 122 scanf("%d",&x); 123 x++; 124 ll cnt=1; 125 ll ans=1; 126 for(int i=1;i<=6;i++) 127 { 128 int tmp=query(i,r[x])-query(i,l[x]-1); 129 cnt=cnt*(ll)(tmp+1)%mod; 130 ans=(ans*fpow(p[i],tmp))%mod; 131 } 132 printf("%I64d %d\n",ans,cnt); 133 } 134 else 135 { 136 int k; 137 ll x; 138 scanf("%d%I64d",&k,&x); 139 k++; 140 update(k,x); 141 } 142 143 } 144 } 145 return 0; 146 }
树状数组
时间: 2024-10-31 10:31:12