返回顶部

CSP26

T1

题目

image

官方题解

image

考虑暴力,发现奇数边包赢,偶数边如果异或和为\(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;
}
posted @ 2024-08-21 15:35  wlesq  阅读(14)  评论(0编辑  收藏  举报