ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

首师大附中集训第四天综合测试

2019-07-29 20:41:04  阅读:257  来源: 互联网

标签:师大附中 return int 综合测试 long fa freopen 第四天 include


综合测试

      考试的前一天老师说今天的题比NOI稍微简单一些

      第一题,给你n,要你求f(1)\ xor\ f(2)\ xor...xor\ f(n)。定义f(i)为其所有约数的异或和。n<=10^{14}.

      这题还是比较简单的,直接数论分块,讨论那些[\frac{n}{l}]为奇数就行了。

      求前缀和的时候考虑相邻两个数(偶奇)的异或和为1.然后讨论一下情况就可以了。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

long long n;
long long ans=0;

long long get_sum(long long x){
	if(x%2==1) return ((x+1)/2)%2;
	else return x^((x/2)%2);
}

int main(){
	//freopen("Xor.in","r",stdin);
	//freopen("Xor.out","w",stdout);
	scanf("%lld",&n);
	long long l=1,r;
	while(l<=n){
		r=n/(n/l);
		if((n/l)&1){
			if(l==r) ans^=l;
			else ans^=get_sum(r)^get_sum(l-1);
		}
		l=r+1;
	}
	printf("%lld",ans);
}

      第二题:给定长度为n的序列,每次给出一个[l,r]和一个x。

      对于每一个询问计算有多少个三元组满足l<=i<j<k<=r\& a_i|a_j|a_k=x

      这题我的做法貌似和其他人不太一样,我是直接考虑补集转化。然后把或操作就变成了与操作。

      接着,对于每一个ai,将他的子集位置上的值加上1,开个前缀数组记录一下,那么一个位置上的值就记录了所有超集的个数。

      对于每一次询问的x,我们考虑一个三元组与的值不为x但在x的位置上被计算的,直接枚举x的超集,容斥一下就可以了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

int n,m;
int p[100010][256];
int a[100010];

long long C(long long x){
	if(x<=2) return 0;
	return 1ll*x*(x-1)*(x-2)/6;
}

long long dfs(int l,int r,int x,int now,int coef){
	if(now==8) {
		return C(p[r][x]-p[l-1][x])*coef;
	}
	long long tot=0;
	tot+=dfs(l,r,x,now+1,coef);
	if(!(x&(1<<now))) tot+=dfs(l,r,x|(1<<now),now+1,-coef);
	return tot;
}

int main(){
	//freopen("Or.in","r",stdin);
	//freopen("Or.out","w",stdout);
	scanf("%d %d",&n,&m);
	int l,r,x;
	for(int i=1;i<=n;i++)  {
		scanf("%d",&x);x^=255;
		for(int j=0;j<=255;j++) {
			p[i][j]=p[i-1][j];
			if((x|j)==x) p[i][j]++;
		}
	}
	while(m--){
		scanf("%d %d %d",&l,&r,&x);x^=255;
		printf("%lld\n",dfs(l,r,x,0,1));
	}
}

      第三题:从这题往后就没有正解了。

      给出一张图,问存不存在两棵生成树没有重边。n<=10,m<=100

      我的做法是直接暴力枚举边是否选(满足第一颗生成树的条件),然后在这个过程中check一下是否存在第二颗生成树。如果不存在就直接返回,因为到后面状态数就越多,所以这个剪枝在前面做就可以了,拿到了非比寻常的55分!

       然而,有人直接每一次做很多次random_shuffle。然后从前往后做两遍最小生成树,就拿到了满分(我补题的时候写了这个东西连样例都过不了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int T;
int n,m;
struct edge{
	int x,y;
}s[110];
int fa[11],size[11],f[11];
bool tf[110],we=false;
int data=4;

int fp(int x){
	if(f[x]!=x) return f[x]=fp(f[x]);
	return x;
}

int findpa(int x){
	if(fa[x]!=x) return findpa(fa[x]);
	return x;
}

bool check(){
	for(int i=1;i<=n;i++) f[i]=i;
	int tot=0;
	for(int i=1;i<=m;i++) if(!tf[i]){
		int fx=fp(s[i].x),fy=fp(s[i].y);
		if(fx!=fy) f[fx]=fy,tot++;
		if(tot==n-1) return true;
	}
	return false;
}

bool dfs(int x,int now){
	if(now==n && check()) return true;
	if(x==m+1 || now==n) return false;
	int fx=findpa(s[x].x),fy=findpa(s[x].y);
	if(dfs(x+1,now)) return true;
	if(fx!=fy){
		if(size[fx]<size[fy]) swap(fx,fy);
		fa[fy]=fx;size[fx]+=size[fy];tf[x]=true;
		if((now>data || check()) && dfs(x+1,now+1)) return true;
		size[fx]-=size[fy],fa[fy]=fy;tf[x]=false;
	}
	return false;
}

int main(){
	//freopen("Game.in","r",stdin);
	//freopen("Game.out","w",stdout);
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;i++) fa[i]=i,size[i]=1;
		for(int i=1;i<=m;i++) scanf("%d %d",&s[i].x,&s[i].y),tf[i]=false;
		printf(dfs(1,1)?"Possible\n":"Impossible\n");
	}
}

      第四题:啊这题真的亏,YY了一个决策单调性,结果最后5分钟hack了自己。

      有两种二元组(x,y),对于两个二元组要你计算(x2-x1)(y2-y1)。其中1必须属于第一种二元组,2必须属于第二种二元组。

      而且要求x1<=x2。问最大值。

      我只会暴力。

      听别人讲:把xy画在二维平面上,然后知道答案就相当于一个矩形的面积。

      接着我们看一下第一类点,知道只有类似下凸壳上面的点才是有用的(这个下凸壳只要求x递增,y递减)。

      第二类点,知道只有类似上凸壳上面的点才是有用的。(同理)

      接着我们把两个序列random_shuffle5次,每次取前2000个点出来算一下点对。就可以拿到95的高分!

      不用暴力,把相邻两个点的交界线算出来,然后相邻两条线算一下交点,就可以知道点在哪一块时可以获得最大价值,用set维护,可以拿到103的高分!

标签:师大附中,return,int,综合测试,long,fa,freopen,第四天,include
来源: https://blog.csdn.net/Deep_Kevin/article/details/97677199

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有