杂题选做(NOIP赛前放松)

 这是一篇轻松没有难度的水题大作战

//练习递归的好题

[NOIP1998 普及组] 幂次方 - 洛谷

#include
#include
#include
using namespace std;
void find(int n)
{
	int y = 0,op = 1;//y表示次幂,op表示答案
	if(n == 0)return;
	while(op <= n)
	{
		y++;
		op *= 2;
	 }
	 y--; 
	 if(y == 0)
	 {
	 	cout<<"2(0)";
	 }
	 if(y == 1)
	 {
	 	cout<<2;
	 }
	 if(y > 1)
	 {
	 	cout<<"2(";
	 	find(y);
	 	cout<<")";
	 }
	 
	 if(n != pow(2,y))
	 {
	 	cout<<"+";
	 	find(n-pow(2,y));
	 }
}


int main()
{
	int n;
	cin>>n;
	find(n);
	return 0;
}

 

 

[NOIP2015 提高组] 信息传递 - 洛谷

//带权并查集
#include
#include
#include
#include
using namespace std;
const int N = 2e5+10;
int fa[N],d[N],a[N]; 
int cnt;
int find(int x)//带权并查集
{
	if(fa[x] == x) return fa[x];//return fa[x]  = find(fa[x]);
	int t = find(fa[x]);//我们需要用到这个父亲节点 
	d[x] += d[fa[x]];//需要累加 一个点到 父亲节点的距离(注意,这里是直接距离)用他上一个点到父亲节点的距离累加起上一个点到他自己本身的这段d[x] 的距离
	fa[x] = t;
	return fa[x];
	
 } 
 
int main()
{
	int n;
	cin>>n;
	for(int i = 1;i <= n;i++)
	{
		cin>>a[i];
	}
	for(int i = 1;i <= n;i++) fa[i] = i;
	int minn = 2e6+10;
	for(int i = 1;i <= n;i++)
	{
		int x = i;
		int y = a[i];
		int xx = find(x);
	    int yy = find(y); 
		if(xx != yy) 
	{
		fa[xx] = yy;
		d[x] = d[y]+1;
	}
	else
	{
		 minn = min(minn,d[y] + 1);//最后加上那条上一个点到本身的一条边
	}				
	}
	
	cout<

P1196 [NOI2002] 银河英雄传说 

 [NOI2002] 银河英雄传说 - 洛谷

#include
#include
#include
#include
using namespace std;
const int N = 30010;
int fa[N],d[N],siz[N];
int find(int x)
{
	if(fa[x] == x)return fa[x];
	int t = find(fa[x]);
	d[x] += d[fa[x]];
	fa[x] = t;
	return fa[x];
}

int main()
{
	int T;
	cin>>T;
	for(int i = 1;i <= 30000;i++)
	{
	fa[i] = i;
	siz[i] = 1; 
	}
	
	for(int i = 1;i <= T;i++)
	{
		char op;
		int x,y;
		cin>>op>>x>>y;
		if(op == 'M')
		{
			int xx = find(x);
			int yy = find(y);
			if(xx != yy)
			{
				d[xx] = siz[yy];
				siz[yy] += siz[xx]; 
				fa[xx] = yy;//不是直接合并到根节点去哦 
			}
		//int x = i;
		//int y = a[i];	
		//不能直接合并,需要加上另外集合的size[y]
		//根节点等于root  
	}
		if(op == 'C')
		{
			int xx = find(x);
			int yy = find(y);
			if(xx != yy)
			{
				puts("-1");
			}
			else 
			{
			cout<

 

【模板】最小生成树 - 洛谷

#include
#include
#include
#include
using namespace std;
int fa[5100];
struct node
{
	int x,y,z;
}a[200010];

bool cmp(node a,node b)
{
	return a.z < b.z;
}

int find(int x)
{
	if(fa[x] != x) return fa[x] = find(fa[x]);
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i = 1;i <= n;i++)fa[i] = i;
	for(int i = 1;i <= m;i++)
	{
		cin>>a[i].x>>a[i].y>>a[i].z;
	}
	sort(a+1,a+m+1,cmp);
	int cnt = 0,sum = 0;
	for(int i = 1;i <= m;i++)
	{
		int xx = find(a[i].x);
		int yy = find(a[i].y);
		if(xx != yy)
		{
			fa[xx] = yy;
			sum += a[i].z;
			cnt++;
		}
		if(cnt == n-1)
		{
			break;
		}
	}
	
		if(cnt < n-1) 
		{
			cout<<"orz"<

 

 [NOI1995] 石子合并 - 洛谷

//区间dp模板
//区间dp的套路就是设置dp[i][j]合并i 到 j堆石子需要的最值,列方程即可
//若是环形,那我们需要展开这个环,扩大两倍 
#include
#include
#include
using namespace std;
const int N = 1e5+10;
int a[N];
int f1[300][300],f2[300][300],sum[N];
int main() 
{
	int n;
	cin>>n;
	for(int i = 1;i <= n;i++)
	{
		cin>>a[i];
		a[i+n] = a[i];
	}
	for(int i = 1;i <= 2 * n;i++)
	{
		sum[i] = sum[i-1] + a[i];
	}
	memset(f2,5,sizeof(f2));
	for(int i = 1;i <= 2 * n;i++)
	{
		f2[i][i] = 0;
	}
	for(int len = 2;len <= n;len++)
	{
		for(int l = 1;l <= 2 * n-len+1;l++)
		{
			int r = l+len-1;
			for(int k = l;k < r;k++)
			{
				f1[l][r] = max(f1[l][r],f1[l][k] + f1[k+1][r] + sum[r] - sum[l-1]);
				f2[l][r] = min(f2[l][r],f2[l][k] + f2[k+1][r] + sum[r] - sum[l-1]);
			}
		}
	}
	int maxx = -0x3f3f3f;
	int minn = 0x3f3f3f;
	for(int i = 1;i <= n;i++)
	{
		maxx = max(maxx,f1[i][i+n-1]);
		minn = min(minn,f2[i][i+n-1]);
	}	
	cout<

 

你可能感兴趣的:(学习笔记,算法分类,c++,学习,算法)