A - Thermometer
按题意判断并输出即可。
时间复杂度\(O(1)\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
double x;
signed main(){cin>>x;if(x>=38) cout<<"1\n";else if(x>=37.5) cout<<"2\n";else cout<<"3\n";return 0;
}
B - Ticket Gate Log
令\(c\)表示当前位应为哪个字符,初始为i
。
从左到右遍历每个字符\(s_i\):
- 如果\(s_i=c\),就将\(c\)取反;
- 如果\(s_i\ne c\),就累加\(1\)的贡献。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int ans=0;
char c='i';
signed main(){cin>>s;for(char i:s){if(i==c) c=(c=='i'?'o':'i');else ans++;}cout<<ans+(c=='o')<<"\n";return 0;
}
C - Variety Split Easy
分别令\(lef_i,rig_i\)表示\(A\)长度为\(i\)的前缀和后缀有多少不同的元素。
则答案为\(\max\limits_{i=1}^{n-1} (lef_i+rig_i)\)。
\(lef,rig\)可以在遍历过程中,用桶计算出来。
可以用数组、unordered_set
等数据结构作为桶。
时间复杂度为\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
#define N 300010
using namespace std;
int n,a[N],ans;
unordered_set<int> se;
int lef[N],rig[N];
signed main(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];se.insert(a[i]);lef[i]=se.size();}se.clear();for(int i=n;i>=1;i--) se.insert(a[i]),rig[i]=se.size();for(int i=1;i<n;i++) ans=max(ans,lef[i]+rig[i+1]);cout<<ans<<"\n";return 0;
}
D - Cubes
因式分解可得:\(x^3-y^3=(x-y)(x^2+xy+y^2)\)。
如果我们可以枚举\(d=x-y\),即\(x=d+y\)……
那我们仅需判断\(N=d[(d+y)^2+(d+y)y+y^2]\),即\(3y^2+3dy+(d^2-\frac{N}{d})=0\)是否有正整数解即可。
由于\(x^2+xy+y^2\ge (x-y)^3\),所以\((x-y)^3\le N\),即\(d\le \sqrt[3]{N}\),因此枚举\(d\)的时间复杂度是\(O(\sqrt[3]{N})\)。
接下来考虑对于每个\(d\),如何判断是否有整数解。
- 可以用二次方程求根公式完成判定,时间复杂度为\(O(1)\),不过实现起来比较繁琐;
- 考虑到二次项、一次项系数都为正,所以上式在\(x>0\)时是单增的,所以我们也可以使用二分法。
显然仅需在\([1,\sqrt N]\)内二分即可,时间复杂度为\(O(\log\sqrt N)\),实现起来较为简单。
代码使用二分法,总时间复杂度为\(O(\sqrt[3]{N}\log\sqrt N)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int solve(int a,int b,int c){int l=1,r=1e9;while(l<r){int x=(l+r+1)>>1;if(a*x*x+b*x+c<=0) l=x;else r=x-1; }return a*l*l+b*l+c==0?l:-1;
}
signed main(){cin>>n;for(int d=1;d*d*d<=n;d++){if(n%d) continue;int y=solve(3,3*d,d*d-n/d);if(~y) cout<<d+y<<" "<<y<<"\n",exit(0);}cout<<"-1\n";return 0;
}
E - Path Decomposition of a Tree
定义\(siz_u\)为子树\(u\)的大小,\(fa_u\)为\(u\)的父节点,\(ch_u\)为\(u\)的子节点个数。
定义\(t_u=siz_u\bmod k\)。不难发现,其含义就是“为了将子树\(u\)的节点全部用链覆盖,子树\(u\)外最少要用多少个节点”。
比如\(t_u=0\)就表示子树\(u\)的答案为Yes
。
选定一个节点作为根节点,开始遍历每棵树,对于节点\(u\),不合法的情况显然只有下面\(3\)种:
- \((\sum\limits_{fa_v=u} [t_v\ne 0])>2\)。
- \((\sum\limits_{fa_v=u} t_v)+1>k\)。
- \(ch_u=2\)且\((\sum\limits_{fa_v=u} t_v)\ne k\)。
时间复杂度\(O(nk)\)。
点击查看代码
#include<bits/stdc++.h>
#define NN 200010
#define int long long
using namespace std;
int n,k;
vector<int> G[NN];
void add(int u,int v){G[u].emplace_back(v);}
int dfs(int u,int fa){int cnt=0,sum=1;for(int i:G[u]){if(i==fa) continue;int t=dfs(i,u);if(!t) continue;if(cnt==2) cout<<"No\n",exit(0);sum+=t,cnt++;}if(sum>k||(cnt==2&&sum!=k)) cout<<"No\n",exit(0);return sum%k;
}
signed main(){cin>>n>>k;for(int i=1,u,v;i<n*k;i++){cin>>u>>v;add(u,v),add(v,u);}dfs(1,0);cout<<"Yes\n";return 0;
}