Codeforces Beta Round #9 (Div. 2 Only)

it2024-11-13  13

*C. Hexadecimal's Numbers

theme:给定数字n,求[1,n]中只由字符0或1构成的数字个数。1<=n<=1e9

solution :只由01组成的数为:

1

10 11

100 101 110 111

1000 1001 1010 1011 1100 1101 1110 1111...

可以看出下一行为上一行每个数*10或*10+1的结果。所以我们可以从1开始递归,每次在当前数的基础上*10,*10+1,直到>n结束。

相当于预处理出从小到大的范围内满足条件的值然后lower_bound()找到n所处位置即可。

#include<bits/stdc++.h> #include<vector> #include<algorithm> using namespace std; #define far(i,t,n) for(int i=t;i<n;++i) #define pk(a) push_back(a) typedef long long ll; typedef unsigned long long ull; using namespace std; int ans=0; ll n; void cnt(ll x) { if(x>n) return; ++ans; cnt(x*10); cnt(x*10+1); } int main() { cin>>n; cnt(1); cout<<ans<<endl; }

D. How many trees?

theme:给定n与h,求所有n个节点的二叉树中,高度<=h(包含根节点及叶子节点)的个数。

solution:用dp[i][j]表示i个节点的二叉树,高度<=h的个数,则状态转移方程为

 , 0<=k<i

由转移方程知每个数是前一列若干数两两相乘,所以要一列一列地算,循环时j在外层循环,初始化所有dp[0][j]=1

#include<bits/stdc++.h> #include<vector> #include<algorithm> using namespace std; #define far(i,t,n) for(int i=t;i<n;++i) #define pk(a) push_back(a) typedef long long ll; typedef unsigned long long ull; using namespace std; ll dp[40][40]; void getDp(int n) { for(int i=0;i<=n;++i) dp[0][i]=1; for(int j=1;j<=n;++j) { for(int i=1;i<=n;++i) for(int k=0;k<i;++k) { dp[i][j]+=dp[k][j-1]*dp[i-k-1][j-1]; } } } int main() { int n,h; cin>>n>>h; getDp(n); ll ans=dp[n][n]-dp[n][h-1]; cout<<ans<<"\n"; }

E. Interesting Graph and Apples

theme:给定n个点和m条边,要求最终达到每个节点都属于且只属于一个经过所有节点的环,问最少还要添加多少条边 。

solution:由题意知最终要形成一个环,所以最终所有节点的度都为2。用并查集,

首先将输入的图形存入并查集形成多个连通分量。并记录每个节点的度。判断是否有度>2的点,直接输出NO。

否则从小到大遍历每个节点,若该节点度<2,则将它与最小的度<2且与它不在同一个并查集的点相连,遍历一遍后整个图将变成一条链。

连接两个度为1的端点,此时形成了一个大环。

最后再判断一下所有节点是不是属于同一个并查集,避免形成多个环。

注意可以由自圈与重边。

#include<bits/stdc++.h> #include<vector> #include<algorithm> using namespace std; #define far(i,t,n) for(int i=t;i<n;++i) #define pk(a) push_back(a) typedef long long ll; typedef unsigned long long ull; using namespace std; int fa[100]; int degree[100]; vector<pair<int,int>>ans; void init(int n) { for(int i=0; i<=n; ++i) fa[i]=i; } int Find(int x) { return fa[x]==x?x:fa[x]=Find(fa[x]); } void unit(int x,int y) { x=Find(x); y=Find(y); fa[y]=x; } int main() { int n,m; while(cin>>n>>m) { ans.clear(); memset(degree,0,sizeof(degree)); init(n); far(i,0,m) { int x,y; scanf("%d%d",&x,&y); degree[x]++; degree[y]++; unit(x,y); } far(i,1,n+1) if(degree[i]>2) { cout<<"NO\n"; return 0; } //连成一条链 far(i,1,n+1) { far(j,i+1,n+1) if(degree[j]<=1&&degree[i]<=1&&Find(i)!=Find(j)) { degree[j]++; degree[i]++; unit(i,j); ans.push_back({i,j}); } } far(i,1,n+1) if(degree[i]>2) { cout<<"NO\n"; return 0; } //连端点成环 int s=0,e=0; far(i,1,n+1) { if(degree[i]<=1) { if(!s) s=e=i; else { if(i!=s) { if(e==s) e=i; } } } } if(s!=0&&e!=0) { ans.push_back({s,e}); unit(s,e); degree[s]++; degree[e]++; } for(int i=1; i<=n; ++i) if(Find(i)!=Find(1)||degree[i]!=2) { cout<<"NO\n"; return 0; } cout<<"YES\n"; int sz=ans.size(); cout<<sz<<"\n"; sort(ans.begin(),ans.end()); far(i,0,sz) printf("%d %d\n",ans[i].first,ans[i].second); } }

 

最新回复(0)