题目
题目描述
有些时候,出题人真的不想写背景(???)
总而言之,月读现在有一棵大小为
N
N
N,树上每条边上有一个数字,月读有
M
M
M次询问,每次询问一对
(
x
,
y
)
(x,y)
(x,y),你需要回答从
x
x
x到
y
y
y的路径上的数字重新排列能否形成一个回文序列,若可行输出Yes
,否则输出No
月读为了加快您的读入,每次询问的
x
,
y
x,y
x,y是通过某种方式生成的,为了加快您的输出,你只需要最后输出回答Yes
的个数和即可
输入格式
第一行:两个整数
N
,
M
N,M
N,M
接下来
N
−
1
N-1
N−1行:三个整数
u
i
,
v
i
,
w
i
u_i,v_i,w_i
ui,vi,wi,描述一条边
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi)与边上的数字
w
i
w_i
wi
接下来一行
A
1
,
B
1
A_1,B_1
A1,B1
M
M
M个询问以如下方式生成
x
i
=
A
i
%
n
+
1
,
y
i
=
B
i
%
n
+
1
x_i=A_i \% n+1,y_i=B_i \% n+1
xi=Ai%n+1,yi=Bi%n+1
A
i
=
A
i
−
1
×
666073
%
(
1
0
9
+
7
)
A_i=A_{i-1} \times 666073 \% (10^9+7)
Ai=Ai−1×666073%(109+7)
B
i
=
B
i
−
1
×
233
%
998244353
B_i=B_{i-1} \times 233 \% 998244353
Bi=Bi−1×233%998244353
输出格式
一行一个数字,代表回答Yes
的个数
样例
样例输入
4 1
1 2 1
2 3 1
1 4 2
2 3
样例输出
1
数据范围与提示
对于此题有六个测试点:
A(
10
10
10分)
N
,
M
⩽
2000
N,M \leqslant 2000
N,M⩽2000
B(
23
23
23分)
N
,
M
⩽
1
0
5
,
u
i
=
v
i
+
1
N,M \leqslant 10^5,u_i=v_i+1
N,M⩽105,ui=vi+1
C(
15
15
15分)
N
,
M
⩽
1
0
5
N,M \leqslant 10^5
N,M⩽105
D(
15
15
15分)
N
,
M
⩽
1
0
6
,
w
i
⩽
30
N,M \leqslant 10^6,w_i \leqslant 30
N,M⩽106,wi⩽30
E(
17
17
17分)
N
,
M
⩽
1
0
6
N,M \leqslant 10^6
N,M⩽106
F(
20
20
20分)
N
⩽
1
0
6
,
M
⩽
1
0
7
N \leqslant 10^6,M \leqslant 10^7
N⩽106,M⩽107
对于所有的
w
i
⩽
n
wi \leqslant n
wi⩽n
题解
如果重新排列能形成一个回文序列的话,那么满足出现的次数是奇数的数字最多只能有一个
所以我们可以对每一种边权进行哈希赋值,和
0
0
0一起存入哈希表中
接着,我们记
X
o
r
i
Xor_i
Xori为根到
i
i
i点的边权异或和
那么,如果询问的点为
x
,
y
x,y
x,y,只要
f
x
∧
f
y
f_x\land f_y
fx∧fy在哈希表里出现过,回答就是
Y
e
s
Yes
Yes
注意:如果你在DTOJ上提交,建议你不要使用C++11(NOI),使用C++11,否则可能会超时
附上代码:
#include<cstdio>
int n,m,Tot,tot,cnt,Head[1000010],Nxt[1000010],head[1000010],to[2000010],ver[2000010],nxt[2000010],dfn[1000010];
unsigned long long POW[1000010],pow[2000010],Ver[1000010];
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void Add(unsigned long long x)
{
int y=x%1000007;
Nxt[++Tot]=Head[y],Head[y]=Tot,Ver[Tot]=x;
}
int Find(unsigned long long x)
{
int y=x%1000007;
for(int i=Head[y];i;i=Nxt[i]) if(Ver[i]==x) return 1;
return 0;
}
void add(int u,int v,int w)
{
nxt[++tot]=head[u],head[u]=tot,to[tot]=v,ver[tot]=w;
}
void dfs(int x,int fa,unsigned long long Pow)
{
dfn[x]=++cnt,pow[cnt]=Pow;
for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa) dfs(to[i],x,POW[ver[i]]),pow[++cnt]=POW[ver[i]];
}
int main()
{
n=read(),m=read(),POW[0]=1,Add(0);
for(int i=1;i<=n;i++) POW[i]=POW[i-1]*793999,Add(POW[i]);
for(int i=1,u,v,w;i<n;i++) u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);
dfs(1,0,(unsigned long long)0);
for(int i=2;i<=cnt;i++) pow[i]^=pow[i-1];
int a,b,ans=0;
a=read(),b=read();
for(int i=1,x,y;i<=m;i++)
x=a%n+1,y=b%n+1,a=666073ll*a%1000000007,b=233ll*b%998244353,ans+=Find(pow[dfn[x]]^pow[dfn[y]]);
printf("%d",ans);
}