NOIP提高组模拟赛夜间版2


没想到这个系列还能再更新

A. 装饰

这种题就需要大胆猜测打表验证

反正就是推出来了,式子变化一下就是题解式子,就是有亿点不简洁

我是这么想的(大概)

先排序,两个较小的颜色可以看成一个,这样只用考虑两种颜色,取法只有\(1-2\)

令两种颜色数量为\(a,b(a

  1. \(a*2<=b\)显然按照\(a\)\(1\),b取\(2\)\(b\)有剩余,答案是\(a\)

  2. \(a*2>b\),那么每次操作可以令两种颜色数量差\(-1\),可以推一下,然后写出一个简单式子,实际上这样的结果是剩下的数量一定为\(0-0,1-0,0-1,1-1,0-2,2-0\),实际上就是\((a+b+c)%3\),那么答案其实就是\((a+b+c)/3\),当然也可以写一堆恶心式子

code
#include
#include
#include

using namespace std;

typedef long long ll;

ll a[4];

ll work(){
	ll ans=0;
	a[2]+=a[1];
	if(a[3]

B. 凉宫春日的消失

感谢数据,让我水了\(65pts\)

发现一定有解,跟\(dfs\)序有关,然后就莽了个按照\(dfs\)序排序

实际上离正解只有一步之遥

我们先让点集里的点按\(dfs\)序排序,然后相邻的两点都进行配对,第一个再和最后一个配对,这样我们把每个点配了两对

想一想深搜的路径,发现此时最多每条边经过两次

也就是说\(\sum_{i=1}^{cnt}path<=2(n-1)\)

我们只需要两两配对,那么只需要保留一半的路径,\(1,3,5....\)或者\(2,4,6....\)

他们有一个一定\(<=n-1\)

简单判断一下一种方案是否可行即可

code
#include
#include
#include

using namespace std;

const int maxn=200005;

struct edge{int net,to;}e[maxn<<1|1];
int head[maxn],tot;
void add(int u,int v){
   e[++tot].net=head[u];
   head[u]=tot;
   e[tot].to=v;
}

int f[maxn][21],dfn[maxn],tim,dep[maxn],ls[maxn];

bool cmp(int x,int y){
	return dfn[x]dep[x]){x^=y;y^=x;x^=y;}
	for(int i=20;i>=0;--i)if(dep[x]-dep[y]>=(1<=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}

bool check(int s,int n){
	if(s&1)return false;
	int sum=0;
	for(int i=1;i<=s;i+=2){
		int lca=LCA(ls[i],ls[i+1]);
		sum+=dep[ls[i]]-dep[lca]+dep[ls[i+1]]-dep[lca];
		if(sum>n)return false;
	}
	return true;
}
int main(){
	freopen("kieru.in","r",stdin);
	freopen("kieru.out","w",stdout);
	int n;scanf("%d",&n);
	for(int i=1;i