【ATcoder】abc361 B-F题解 atcoder beginner contest361
Posted on 2024-07-08 00:47 木易meow 阅读(144) 评论(0) 编辑 收藏 举报B-Intersection of Cuboids
传送门:
B - Intersection of Cuboids (atcoder.jp)
简单题意
给定两个长方体 判断是否有重合体积
思路:
假设有重合体积,那么重合部分一定是个长方体。如果是长方体一定在三个坐标轴的投影都有一段长度。所以问题转化为判断两个长方体在三个坐标轴上是否都有一段交集
code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int MAXN=2e5+10;
int a[7],b[7];
void sol(){
for(int i=1;i<=6;i++)cin>>a[i];
for(int i=1;i<=6;i++)cin>>b[i];
int f=1;
if(b[1]>=a[4] || a[1]>=b[4])f=0;
if(b[2]>=a[5] || a[2]>=b[5])f=0;
if(b[3]>=a[6] || a[3]>=b[6])f=0;
if(!f)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sol();
}
C Make Them Narrow
传送门:
C - Make Them Narrow (atcoder.jp)
简述题意:
可以从n个数里面移走k个数,求出移走后的最小极差
思路:
因为极差只与最大最小有关,所以分别讨论从小开始移走0-k个(对应从大的一端移走k-i个)的极差。
code
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int MAXN=2e5+10;
const int inf=0x3f3f3f3f;
int a[MAXN];
bool cmp(int x,int y){
return x<y;
}
void sol(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1,cmp);
int ans=inf;
for(int i=0;i<=k;i++){
int res=a[n-k+i]-a[1+i];
ans=min(ans,res);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sol();
}
D Go Stone Puzzle
传送门
D - Go Stone Puzzle (atcoder.jp)
题意简述:
给你长度为N的串和两个空位(排在串的右侧),每次可以移动两个相邻的石块平移到空位上,问能不能经过有限次的移动将原串转化为新串
思路:
根据数据范围N<=14提示高复杂度算法,再加上询问最小次数,所以考虑BFS。
warning:
一旦字符串下标越界就会变得非常慢!!!
code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int MAXN=2e5+10;
struct node{
string s;
int opt;
int kb;
};
int n;
string s,t;
map<string,int>mp;
void sol(){
cin>>n;
cin>>s>>t;
s=s+' '+' ';
t=t+' '+' ';
queue<node>q;
q.push({s,0,});
while(!q.empty()){
auto fr=q.front();
q.pop();
s=fr.s;
if(s==t){
cout<<fr.opt<<endl;
return ;
}
int wr=0;
for(int i=0;i<n+1;i++){
if(s[i]==' '){
wr=i;
break;
}
}
string str;
for(int i=0;i<wr-1;i++){
str=s;
str[wr]=str[i];
str[wr+1]=str[i+1];
str[i]=' ';
str[i+1]=' ';
if(mp[str])continue;
q.push({str,fr.opt+1});
mp[str]=1;
}
for(int i=wr+2;i<n+1;i++){
str=s;
str[wr]=str[i];
str[wr+1]=str[i+1];
str[i]=' ';
str[i+1]=' ';
if(mp[str])continue;
q.push({str,fr.opt+1});
mp[str]=1;
}
}
cout<<-1<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sol();
}
E - Tree and Hamilton Path 2
传送门:
E - Tree and Hamilton Path 2 (atcoder.jp)
题意简述:
给你一棵树,问从任意起点开始,最小的从一个点出发,经过所有点的路径的长度
思路:
很显然对于每一个分支需要一去一回走两次,除了从起点到终点的路只需要走一次。所以我们需要找到最大的从起点到终点的路径——即树的直径。
code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int MAXN=2e5+10;
#define f first
#define s second
vector<pair<int,int> >e[MAXN];
int n,ans;
int dp[MAXN];
void dfs(int u,int fa,int ww){
for(auto i:e[u]){
int v=i.f,w=i.s;
if(v==fa)continue;
dfs(v,u,w);
ans=max(ans,dp[u]+dp[v]);
dp[u]=max(dp[v],dp[u]);
}
dp[u]+=ww;
}
void sol(){
int tot=0;
cin>>n;
int u,v,w;
for(int i=1;i<n;i++){
cin>>u>>v>>w;
e[u].push_back({v,w});
e[v].push_back({u,w});
tot+=w;
}
dfs(1,0,0);
cout<<tot*2-ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sol();
}
F - x = a^b
传送门:
题意简述:
给定N,问1-N中有多少个数可以表示为a的b次方(b>1)的形式。
思路:
因为N的范围是1e18,所以当b=2的时候最大的a为1e9,很显然这个复杂度是不能接受的,但是根据常识我们可以知道当一个数的平方小于n的时候,所有比这个数小的数的平方都将比n小,因此通过sqrt()函数我们可以O(1)的求出。
接着考虑b>2,此时最大的a为1e6,于是我们可以遍历一遍a,同时统计每个a的次方。(注意标vis数组,避免重复计算)
由于4的次幂一定都是2的次幂,所以一旦我们更新次幂的时候发现已经被更小的标记过了,那么就可以直接break掉。
由于部分数可能既是一个数的平方又是一部分数的高次幂,所以我们需要在筛除的时候判断一下是不是一个平方数,最后再进行一下简单容斥
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
map<int,int>vis;
void sol(){
int n;
cin>>n;
int ans=0,tot=0;
for(int i=2;i*i*i<=n;i++){
int res=i*i;
while(res<=n/i){
res*=i;
if(vis[res])break;
ans++;
vis[res]=1;
if(((int)sqrtl(res))*((int)sqrtl(res))==res){
tot++;
}
}
}
// cerr<<sqrt(n)<<' '<<ans<<' '<<tot<<endl;
ans=ans+((int)sqrtl(n))-tot;
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
sol();
}