第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)


A Matrix Equation +++

B Number Game ???

C Stone Game ---

D Fight against involution ---

E Tree Transform ???

F Gcd Product ???

G Xor Transformation ---

H Path Killer ???

I Random Walk On Tree ---

J Tree Constructer !!!

构造题 难想啊
因为树是天然的二分图
我们先黑白染色 个数少的为基准(原因后面讲)
然后排列成二分图的形式
以左侧为基准(假设左侧个数少)
首先左侧的点自己不能连边 所以低两位为10
右侧同理 但是右侧得和左侧连边 所以右侧低两位是01
左侧的点初始值设为 2^60-1-1
右侧的点初始值设为 1
然后依次考虑左侧的点 从第3位(由低到高)开始 去掉这一位
在与他相邻的点中加上这一位 这样就构成了锁和钥匙的形式

#include<bits/stdc++.h>
using namespace std;
const int N = 105;
vector<int>to[N];
typedef long long ll;
const ll inf = (1ll<<60)-1ll;
ll val[N];
#define pb push_back
vector<int>f[2];
void dfs(int u,int fa,int d){
	f[d].pb(u);
	for(auto v:to[u]){
		if(v==fa) continue;
		dfs(v,u,d^1);
	}
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i = 1; i < n; i++){
		int x,y;
		scanf("%d%d",&x,&y);
		to[x].pb(y);
		to[y].pb(x);
	}
	dfs(1,0,0);
	if((int)f[0].size()>(int)f[1].size())
		swap(f[0],f[1]);
	
	for(auto v:f[0]){
		val[v]=inf-1ll;		
	}
	
	for(auto v:f[1]){
		val[v]=1;
	}
	ll now=2ll;
	for(auto v:f[0]){
		val[v]^=(1ll<<now);
		for(auto k:to[v]){
			val[k]|=(1ll<<now);
		}
		now++;
	}
	for(int i = 1; i <= n; i++) printf("%lld%c",val[i],i==n?'\n':' ');
	return 0;
}

K Kth Query ???

L Bit Sequence !!!

一道数位dp,首先m的大小并不是很大,所以数位dp到最后一位的值可以直接遍历m,现在就是要存哪些状态了,100是小于2的七次方也就是128的,所以加上一个小于m的值最多会影响第八位小后的那些连续的1,我们把这些连续的1的奇偶存起来,如果是奇数的话加上那个小于m的值进位后还是奇数,不影响,但是偶数的话会变成奇数,改变了奇偶性,还有就是后七位要存起来,第八位以后的一的个数也要存起来,具体看代码
pos是位置,h是后七位的值,g是第八位之后的连续1的个数,c是第八位之后的1的奇偶性,flag是限制

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
ll dp[70][128][2][2][2];
ll w[150],a[150];
int m;
ll x;
ll get(int h,int g,int c){
	int ans=1;
	if(g==1)g=0;
	else g=1;
	for(int i=0;i<m;i++){
		if(i+h>=128){
			if((__builtin_parity((i+h)%128)^c^g)!=a[i])ans=0;
		}
		else{
			if((__builtin_parity((i+h)%128)^c)!=a[i])ans=0;
		}
	}
	return ans;
}
ll dfs(int pos,int h,int g,int c,int flag){
	if(pos==0){
		return get(h,g,c);
	}
	if(dp[pos][h][g][c][flag]!=-1)return dp[pos][h][g][c][flag];
	int maxn=1;
	if(flag==1)maxn=w[pos];
	ll ans=0;
	for(int i=0;i<=maxn;i++){
		if(pos>=8){
			if(i==1){
				ans=ans+dfs(pos-1,h,g^1,c^i,flag&(i==maxn));
			}
			else{
				ans=ans+dfs(pos-1,h,0,c^i,flag&(i==maxn));
			}
		}
		else{
			ans=ans+dfs(pos-1,2*h+i,g,c,flag&(i==maxn));
		}
	}
	dp[pos][h][g][c][flag]=ans;
	return ans;
}
ll solve(){
	int cnt=0;
	while(x!=0){
		w[++cnt]=x%2;
		x=x/2;
	}
	return dfs(cnt,0,0,0,1);
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		memset(dp,-1,sizeof(dp));
		scanf("%d %lld",&m,&x);
		for(int i=0;i<m;i++){
			scanf("%d",&a[i]);
		}
		printf("%lld\n",solve());
	}
}

M Cook Pancakes! ---


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM