码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP hzwer third - xgtao -

时间:2016-08-03 08:59:36      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

技术分享

 

 

题意


给出一个1~n的序列,每一次都可以选择一些数减去1,问最小次数使得所有数都为0是多少?

 

题解

1.可以先模拟最优策略,那么很显然,每次选择一半的数就是最优的。

技术分享

 

代码

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

int n,cnt;

int main(){
	freopen("seq.in","r",stdin);
	freopen("seq.out","w",stdout);
	scanf("%d",&n);
	while(n){
		n>>=1;
		cnt++;
	}
	cout<<cnt<<endl;
	return 0;
}

  

技术分享

技术分享

技术分享

 

题意

求出一个点到其他所有点的最大权值,而这个一个点u到另外一个点v的权值是u到v整个路径的最小边权。

 

题解

1.最暴力的做法就是枚举每一点算出到每一个点的的权值,再加起来求max。

2.由于数据范围一般是nlogn或者n,那么就不枚举点了,枚举边但是边要受权值小的的限制,那就直接从大到小排序不就好了就没有后效性了。

3.对于一条边连着左右两部分,当考虑到这一条边的时候,这一条边的权值一定是相对于考虑过的边是最小的w,就先用并查集把边相连的两部分连在一起。

4.假设我们想要的那个点在左边,那么左边的权值ResLeft就应该加上右边的点数RightSize*w,整体的权值为ResLeft = ResLeft+RightSize*w,假设我们想要的那个点在右边,那么右边边的权值ResRight就应该加上右边的点数LeftSize*w,整体的权值就为ResRight = ResRight+LeftSize*w,然后这个整体的权值就是max(ResLeft,ResRight)

 

代码

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

const int N = 500010;
int fa[N],size[N],n,u,v,w,res[N];

struct Edge{
	int u,v,w;
	bool operator < (const Edge&rhs)const{return w > rhs.w;}
}edge[N<<1];

int find(int x){
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main(){
	freopen("ljqz.in","r",stdin);
	freopen("ljqz.out","w",stdout);
	scanf("%d",&n);
	for(int i = 1;i < n;++i){
		scanf("%d%d%d",&u,&v,&w);
		edge[i] = (Edge){u,v,w};
	}
	sort(edge+1,edge+n);
	for(int i = 1;i <= n;++i)fa[i] = i,size[i] = 1;
	for(int i = 1;i < n;++i){
		int fx = find(edge[i].u),fy = find(edge[i].v);
		if(fx != fy)fa[fx] = fy;
		res[fx] += size[fy]*edge[i].w;
		res[fy] += size[fx]*edge[i].w;
		size[fy] += size[fx];
		res[fy] = max(res[fy],res[fx]);
	}
	cout<<res[find(n)]<<endl;
	return 0;
}

  

 

技术分享

技术分享

技术分享

技术分享

 

题意

给出方针左上角的点,要求横向纵向斜向都为素数,并且位数和为sum,按字典序输出质数方阵

 

题解

 

一.最暴力的方法就是枚举矩阵里面的每一个数为O(1025).

二.其次暴力可以打表的就是把以某一个数开头的素数记录下来,枚举第一行,再枚举第一二三四五列,最后再判断是否满足条件。

三.0.正解就是优美的暴力,涨姿势了。

  1.因为很显然的就是每一个素数都是以1,3,7,9结尾的,那么最后一行和最后一列的素数组成都为1,3,7,9限制级别为最高。

  2.其次就是斜行相交的格子的数要相同,并且会受到最后一行和最后一列和左上角那个点的影响,限制级别其次。

  3.然后就可以通过填过的数字直接暴力枚举了,限制级别最低。

    4.最后就可以通过枚举的数字算出一些格子,来判断是否符合条件。

 

就按照限制级别开始枚举,流程图:

技术分享

 

代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100000;


#define clr(a,b) memset(a,b,sizeof(a))
int primelist[N],las[N];
int map[5][5],sum,hash[10][10][10][10][10],tot,b[10][110][10],a[10][10][100],vis[N],num[5];

struct res{
	int x[5];
	bool operator < (const res &rhs)const{
		if(x[0] == rhs.x[0] && x[1] == rhs.x[1] && x[2] == rhs.x[2] && x[3] == rhs.x[3])return x[4]<rhs.x[4];
		if(x[0] == rhs.x[0] && x[1] == rhs.x[1] && x[2] == rhs.x[2])return x[3] < rhs.x[3];
		if(x[0] == rhs.x[0] && x[1] == rhs.x[1])return x[2] < rhs.x[2];
		if(x[0] == rhs.x[0])return x[1] < rhs.x[1];
		return x[0] < rhs.x[0];
	}
}ans[300];

void DfsElse(int va,int vb,int vc,int vd){
	map[0][1] = va/10000,map[2][1] = (va/100)%10;
	map[0][3] = vb/10000,map[2][3] = (vb/100)%10;
	map[1][0] = vc/10000,map[1][2] = (vc/100)%10;
	map[3][0] = vd/10000,map[3][2] = (vd/100)%10;
	map[0][2] = sum-map[0][0]-map[0][1]-map[0][3]-map[0][4];
	map[2][0] = sum-map[2][1]-map[2][2]-map[2][3]-map[2][4];
	if(map[0][2]<= 0||map[0][2]>9||map[2][0]<= 0||map[2][0]>9)return;
	if(map[0][2]+map[1][2]+map[2][2]+map[3][2]+map[4][2] != sum)return;
	if(map[0][0]+map[0][1]+map[0][2]+map[0][3]+map[0][4] != sum)return;
	if(!hash[map[0][0]][map[0][1]][map[0][2]][map[0][3]][map[0][4]])return;
	if(!hash[map[0][2]][map[1][2]][map[2][2]][map[3][2]][map[4][2]])return;
	if(!hash[map[2][0]][map[2][1]][map[2][2]][map[2][3]][map[2][4]])return;
	if(!hash[map[0][0]][map[1][0]][map[2][0]][map[3][0]][map[4][0]])return;
	++tot;
	for(int i = 0;i < 5;++i){
		for(int j = 0;j < 5;++j){
			ans[tot].x[i] = ans[tot].x[i]*10+map[i][j];
		}
	}
}

void DfsMid(int va,int vb){
	for(int i = 4;i >= 0;--i)map[i][i] = va % 10,va /= 10;
	for(int i = 4;i >= 0;--i)map[4-i][i] = vb % 10,vb /= 10;
	int cnt1 = b[map[1][1]][map[3][1]*10+map[4][1]][0];
	int cnt2 = b[map[1][3]][map[3][3]*10+map[4][3]][0];
	int cnt3 = b[map[1][1]][map[1][3]*10+map[1][4]][0];
	int cnt4 = b[map[3][1]][map[3][3]*10+map[3][4]][0];
	//	printf("%d %d %d %d\n",cnt1,cnt2,cnt3,cnt4);
	for(int i = 1;i <= cnt1;++i)
		for(int j = 1;j <= cnt2;++j)
			for(int k = 1;k <= cnt3;++k)
				for(int l = 1;l <= cnt4;++l)
	DfsElse(b[map[1][1]][map[3][1]*10+map[4][1]][i],b[map[1][3]][map[3][3]*10+map[4][3]][j],b[map[1][1]][map[1][3]*10+map[1][4]][k],b[map[3][1]][map[3][3]*10+map[3][4]][l]);
}

void DfsUnderAndRight(int va,int vb){
	for(int i = 4;i >= 0;--i)map[4][i] = va % 10,va /= 10;
	for(int i = 4;i >= 0;--i)map[i][4] = vb % 10,vb /= 10;
	int cnt1 = a[map[0][0]][map[4][4]][0];
	int cnt2 = a[map[4][0]][map[0][4]][0];
//	printf("%d %d\n",cnt1,cnt2);
	for(int i = 1;i <= cnt1;++i){
		for(int j = 1;j <= cnt2;++j){
			int x = a[map[0][0]][map[4][4]][i];
			int y = a[map[4][0]][map[0][4]][j];
			if((x/100)%10 == (y/100)%10)DfsMid(x,y);
		}
	}
}

int main(){
	freopen("prime.in","r",stdin);
	freopen("prime.out","w",stdout);
	scanf("%d%d",&sum,&map[0][0]);
	for(int i = 2;i <= N;++i)if(!vis[i]){
		primelist[++primelist[0]] = i;
		for(int j = 2*i;j <= N;j += i)vis[j] = 1;
	}
	for(int i = 1;i <= primelist[0];++i)if(primelist[i]>=10000){
		int x = primelist[i],numcnt = 5,add = 0,flag = 1;clr(num,0);
		while(x){
			add += x%10;
			if(x%2 == 0 || x%10 == 5)flag = 0;
			x /= 10;
		}
		if(add != sum)continue;
		x = primelist[i];
		if(flag)las[++las[0]] = x;
		a[x/10000][x%10][++a[x/10000][x%10][0]] = x;
		b[(x/1000)%10][x%100][++b[(x/1000)%10][x%100][0]] = x;
		hash[x/10000][(x/1000)%10][(x/100)%10][(x/10)%10][x%10] = 1;
	}
//	for(int i = 1;i <= las[0];++i)printf("%d ",las[i]);
	for(int i = 1;i <= las[0];++i){
		for(int j = 1;j <= las[0];++j){
			if(las[i]%10 == las[j]%10)DfsUnderAndRight(las[i],las[j]);
		}
	}
	sort(ans+1,ans+tot+1);
	for(int i = 1;i <= tot;++i){
		for(int j = 0;j < 5;++j)printf("%d\n",ans[i].x[j]);
		puts("");
	}
	return 0;
}

  

NOIP hzwer third - xgtao -

标签:

原文地址:http://www.cnblogs.com/xgtao984/p/5731416.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!