C - Tree and LCS
服了,又不会构造题了。。。
答案是 1 1 1。
最初的想法是构造一个小根堆和一个大根堆,后来想了一下感觉没法处理路径的情况。
然后看了一下题解,哦,把叶子节点两两配对就行了,看起来很对的样子。其实也就相当于 p p p序列是把这条路径翻转过来了。那么问题来了,为什么我当时就没想到呢?
数据范围你也诈骗人呢?
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
int n,in[5005],p[5005];
vector<int>g[5005];
queue<int>Q;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<n;i++){
int x,y;cin>>x>>y,g[x].pb(y),g[y].pb(x),in[x]++,in[y]++;
}for(int i=1;i<=n;i++)if(in[i]==1)Q.push(i);
int x=0;
while(Q.size()){
int y=Q.front();Q.pop();
if(x)p[x]=y,p[y]=x,x=0;
else x=y;
for(auto z:g[y]){
if(--in[z]==1)Q.push(z);
}
}if(x)p[x]=x;
for(int i=1;i<=n;i++)cout<<p[i]<<' ';
}
D - Xor Sum 5
考虑用生成函数来解决这个问题。
相当于求所有 S S S的异或和,其中 [ x S ] ( x A 1 + x A 2 + . . . + x A n ) K [x^S](x^{A_1}+x^{A_2}+...+x^{A_n})^K [xS](xA1+xA2+...+xAn)K的值为 1 1 1(在模 2 2 2意义下)
注意到 ( x A 1 + x A 2 + . . . + x A n ) 2 k = x A 1 2 k + x A 2 2 k + . . . + x A n 2 k (x^{A_1}+x^{A_2}+...+x^{A_n})^{2^k}=x^{A_12^k}+x^{A_22^k}+...+x^{A_n2^k} (xA1+xA2+...+xAn)2k=xA12k+xA22k+...+xAn2k
记 K = ∑ i = 1 M 2 k i K=\sum_{i=1}^M2^{k_i} K=∑i=1M2ki,那么原多项式可以写成:
[ x S ] ∏ i = 1 M ( x A 1 2 k i + x A 2 2 k i + . . . + x A n 2 k i ) [x^S]\prod_{i=1}^M(x^{A_12^{k_i}}+x^{A_22^{k_i}}+...+x^{A_n2^{k_i}}) [xS]∏i=1M(xA12ki+xA22ki+...+xAn2ki)
这样相当于算 ∑ i = 1 M A X i 2 k i \sum_{i=1}^MA_{X_i}2^{k_i} ∑i=1MAXi2ki的异或和, K K K的范围就大大缩小了。
最无脑的想法就是直接背包。然而应该注意到,其体积的形式为 A X i 2 k i A_{X_i}2^{k_i} AXi2ki,也就是说在 A i A_i Ai的二进制表示下在末尾添 k i k_i ki个零,显然后 k i k_i ki位的值不会发生变化,因此我们可以提前将后 k i k_i ki位的答案确定出来,稍加分析可知背包容量只需要 2 max ( A i ) 2\max(A_i) 2max(Ai),总复杂度 O ( n A i log K ) O(nA_i\log K) O(nAilogK)。
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
int n,m,A,a[2005],p[2005],dp[2005],dp2[2005],ans1[2005],ans2[2005];
ll K,tot;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>K;for(int i=1;i<=n;i++)cin>>a[i],A=max(A,a[i]);
int b=0;
while(K){
if(K&1)p[++m]=b;
K>>=1,b++;
}dp[0]=1;
for(int i=1;i<=m;i++){
memset(dp2,0,sizeof dp2),memset(ans1,0,sizeof ans1);
ll mo=1ll<<p[i]-p[i-1];
for(int j=0;j<=2*A;j++){
if(dp[j]){
for(int k=1;k<=n;k++){
dp2[a[k]+j/mo]^=1;
ans1[j%mo]^=1;
}
}
}if(n&1){
ll res=0;
for(int j=0;j<=2*A;j++){
if(ans1[j]){
res^=j;
}
}tot+=res<<p[i-1];
}
if(i==m){
ll res=0;
for(int j=0;j<=2*A;j++){
if(dp2[j]){
res^=j;
}
}tot+=res<<p[i];
cout<<tot;
}memcpy(dp,dp2,sizeof dp2);
}
}