CSP26
T1
题目
官方题解
考虑暴力,发现奇数边包赢,偶数边如果异或和为\(0\)则输,当然也有特例,比如\(2->4->8->14->\),这\(4\)条边异或为\(0\)但其实必赢,
所以,为了避免这种情况发生,我们使用\(hash\)
XORHashing
这样与处理出\(dis\),两点\(u,v\)即为\(dis_u xor dis_v\)
暴力的话\(O(n^2)\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int N = 5e5+5;
const ull B=233;
ull qpow(ull a,ull b)
{
ull ans=1;
while(b)
{
if(b&1)ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
int n,dep[N];ull dis[N];int f[N][24];
vector <pii> edge[N];
map <int,int> mp;
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
// cout<<u<<endl;
// f[u][0]=fa;
// for(int i=1;i<=20;i++)
// f[u][i]=f[f[u][i-1]][i-1];
for(auto [to,w]:edge[u])
{
if(to==fa)continue;
dis[to]=dis[u]^w;
dfs(to,u);
// mp[dis[to]]++;
}
}
int lca(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=20;i>=0;i--)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return 0;
for(int i=20;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
ll C(ll n)
{
return 1ll*n*(n-1)/2ll;
}
int get(int u,int v)
{
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
int main()
{
speed();
// freopen("T1.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n;int u,v;ull w;
// while(q.size())q.pop();
for(int i=1;i<=n;i++)edge[i].clear();
for(int i=1;i<=n-1;i++)
{
cin>>u>>v>>w;
// cout<<u<<" "<<v<<" "<<w<<endl;
w=qpow(B,w);
edge[u].pb({v,w});edge[v].pb({u,w});
}
ll ans=C(n);
dfs(1,0);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(dis[i]^dis[j])continue;
// if(get(i,j)%2)continue;
// cout<<i<<" "<<j<<endl;
ans--;
}
}
cout<<ans<<endl;
}
return 0;
}
/*
hack
1
5
1 2 2
2 3 4
3 4 8
4 5 14
*/
正解,其实很好想,开个桶记录一下\(dis\)最后统计答案即可,注意相同内部两两组合
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
#define pii pair<int,ull>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
using namespace std;
const int N = 5e5+5;
const ull B=233;
ull qpow(ull a,ull b)
{
ull ans=1;
while(b)
{
if(b&1)ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
int n,dep[N],un,tong[N];ull dis[N];int f[N][24];
vector <pii> edge[N];
map <ull,int> mp;
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
for(auto [to,w]:edge[u])
{
if(to==fa)continue;
dis[to]=dis[u]^w;
// cout<<dis[to]<<endl;
mp[dis[to]]++;
dfs(to,u);
// mp[dis[to]]++;
}
}
ll C(ll n)
{
return 1ll*n*(n-1)/2ll;
}
int main()
{
speed();
// freopen("T1.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n;int u,v;ull w;
mp.clear();
// while(q.size())q.pop();
for(int i=1;i<=n;i++)edge[i].clear(),dis[i]=0;
for(int i=1;i<=n-1;i++)
{
cin>>u>>v>>w;
// cout<<u<<" "<<v<<" "<<w<<endl;
w=qpow(B,w);
edge[u].pb({v,w});edge[v].pb({u,w});
}
ll ans=C(n);
dfs(1,0);
mp[0]++;
for(int i=1;i<=n;i++)
{
if(mp[dis[i]]>1)
{
// cout<<mp[dis[i]]<<endl;
ans-=C(mp[dis[i]]);
mp[dis[i]]=0;
}
}
cout<<ans<<endl;
}
return 0;
}
/*
hack
1
5
1 2 2
2 3 4
3 4 8
4 5 14
*/
T2
发现\(i\)为奇数向右跳,偶数向左跳
考虑暴力\(dp\),\(O(kn^2)\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
#define int ll
using namespace std;
const int N = 1e3+5,mod=23333333;
ll n,k,a[N],sum[N],mx;ll ans;
ll dp[N][N];
signed main()
{
speed();
// freopen("T2.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
memset(dp,-1,sizeof dp);
dp[0][1]=0;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=j&&i&1;k++)
{
if(dp[i-1][k]<0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[j]-sum[k-1]);
}
for(int k=j;k<=n&&!(i&1);k++)
{
if(dp[i-1][k]<0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[k]-sum[j-1]);
}
// dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][1]+a[j]);
// dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][0]+a[j]);
}
}
ll ans=0;
for(int i=1;i<=n;i++)
{
ans=max({ans,dp[k][i]});
}
cout<<ans<<endl;
}
return 0;
}
瞎搞做法,骗分专用,\(k\)跑\(100\)次就够,剩下的直接算
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
// #define endl '\n'
#define pii pair<int,int>
#define ull unsigned long long
#define pb push_back
#define ts cout<<"----------------"<<endl;
#define bs bitset<65>
#define int ll
using namespace std;
const int N = 1e3+5,mod=23333333;
ll n,k,a[N],sum[N],mx;ll ans;
ll dp[105][N];
signed main()
{
speed();
// freopen("T2.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n>>k;
int L=0,R=0;ll mx=0;
for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(sum[j]-sum[i-1]>mx)
{
mx=sum[j]-sum[i-1];
L=i,R=j;
}
}
}
memset(dp,-1,sizeof dp);
dp[0][1]=0;
for(int i=1;i<=min(k,100ll);i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=j&&i&1;k++)
{
if(dp[i-1][k]<0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[j]-sum[k-1]);
}
for(int k=j;k<=n&&!(i&1);k++)
{
if(dp[i-1][k]<0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[k]-sum[j-1]);
}
// dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][1]+a[j]);
// dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][0]+a[j]);
}
}
ll ans=0;
if(k>1e2)
{
// ts;
for(int i=1;i<=n;i++)
{
if(i>=L&&i<=R)
{
// cout<<dp[10000][i]<<" ";
if(dp[100][i]<0)continue;
ans=max(ans,dp[100][i]+max(sum[R]-sum[i-1],sum[i]-sum[L-1])+1ll*(k-101)*(sum[R]-sum[L-1]));
}
}
}else
for(int i=1;i<=n;i++)
{
ans=max({ans,dp[k][i]});
}
cout<<ans<<endl;
}
return 0;
}