链接: http://codeforces.com/problemset/problem/633/G
题意: 现在有一颗有根树,每个节点有一个权值,有两种操作,第一对于u这颗子树的所有节点+x ,第二 查询u的子树中有多少节点的权值可以用p+k*m 表示 统计p的个数!!!(也就是相当于问你u的子树中有多少节点的权值%m之后是个素数并且统计素数对的个数)
思路: 因为m并不大,所以这个题就直接bitset 来统计m内的数是否在子树中出现过,然后与一下m之内的素数就是答案。
循环移位技巧: 对于长度为 len 的 bitset向左循环移位x 位就相当于 bs=(bs<<x)|(bs>>(len-x)).
大神舍友代码:
https://blog.csdn.net/sunyutian1998/article/details/82433028
daima :
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
const int N =1e5+5;
struct node
{
int l,r;
ll lz;
bitset<1005>bs;
}tr[N<<2];
ll a[N];
ll val[N];
vector<int >ve[N];
int L[N],R[N];
int tim;
int n,m;
bitset<1005> prime;
bitset<1005> aim;
void init()
{
prime.set();
prime[0]=prime[1]=0;
for(int i=2;i<m;i++){
if(prime[i]==0) continue;
for(int j=2*i;j<m;j+=i){
prime[j]=0;
}
}
}
void push_up(int i)
{
tr[i].bs=tr[i].bs&aim;
tr[i].bs=(tr[lson].bs|tr[rson].bs);
tr[i].bs=tr[i].bs&aim;
}
void push_down(int i)
{
if(tr[i].lz){
ll &lz=tr[i].lz;
lz%=m;
if(lz!=0)
{
tr[lson].bs=tr[lson].bs&aim;
tr[rson].bs=tr[rson].bs&aim;
tr[lson].bs=((tr[lson].bs<<lz)|(tr[lson].bs>>(m-lz)));
tr[rson].bs=((tr[rson].bs<<lz)|(tr[rson].bs>>(m-lz)));
tr[lson].lz+=lz; tr[lson].lz%=m;
tr[rson].lz+=lz; tr[rson].lz%=m;
tr[lson].bs=tr[lson].bs&aim;
tr[rson].bs=tr[rson].bs&aim;
}
lz=0;
}
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r; tr[i].lz=0;
tr[i].bs.reset();
if(l==r){
tr[i].bs[(val[l]%m)]=1;
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
}
void update(int i,int l,int r,ll lz)
{
if(tr[i].l==l&&tr[i].r==r){
tr[i].lz+=lz;
tr[i].bs=(tr[i].bs&aim);
tr[i].bs=((tr[i].bs<<lz)|(tr[i].bs>>(m-lz)));
tr[i].bs=(tr[i].bs&aim);
return ;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) update(lson,l,r,lz);
else if(l>mid) update(rson,l,r,lz);
else{
update(lson,l,mid,lz);
update(rson,mid+1,r,lz);
}
push_up(i);
}
bitset<1005> query(int i,int l,int r)
{
if(tr[i].l==l&&tr[i].r==r){
return tr[i].bs;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) return query(lson,l,r);
else if(l>mid) return query(rson,l,r);
else{
return (query(lson,l,mid)|query(rson,mid+1,r));
}
}
void dfs(int u,int fa)
{
tim++;
L[u]=tim;
for(int i=0;i<ve[u].size();i++){
int v=ve[u][i];
if(v==fa) continue;
dfs(v,u);
}
R[u]=tim;
}
int main()
{
scanf("%d %d",&n,&m);
aim.set();
for(int i=m;i<1005;i++) aim[i]=0;
init();
int u,v;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
ve[u].push_back(v);
ve[v].push_back(u);
}
dfs(1,-1);
for(int i=1;i<=n;i++){
val[L[i]]=a[i];
}
build(1,1,n);
int q;
int op,l,r;
ll x;
scanf("%d",&q);
while(q--)
{
scanf("%d %d",&op,&u);
if(op==1){
scanf("%lld",&x);
l=L[u]; r=R[u];
x%=m;
if(x!=0)update(1,l,r,x);
}
else{
l=L[u]; r=R[u];
bitset<1005> tmp=query(1,l,r);
tmp=tmp′
int ans=tmp.count();
printf("%d\n",ans);
}
}
return 0;
}