这是一篇轻松没有难度的水题大作战
//练习递归的好题
#include<iostream>
#include<cstdio>
#include<cmath>
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;
}
//带权并查集
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
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<<minn<<endl;
return 0;
}
P1196 [NOI2002] 银河英雄传说
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
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<<abs(d[x]-d[y])-1<<endl;//这是套用了前缀和思想
}
}
}
return 0;
}
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
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"<<endl;
}
else
{
cout<<sum<<endl;
}
return 0;
}
//区间dp模板
//区间dp的套路就是设置dp[i][j]合并i 到 j堆石子需要的最值,列方程即可
//若是环形,那我们需要展开这个环,扩大两倍
#include<iostream>
#include<algorithm>
#include<cstring>
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<<minn<<endl<<maxx;
return 0;
}