Codeforces Round 1025 (Div. 2)(A-D)
题目链接:Dashboard - Codeforces Round 1025 (Div. 2) - Codeforces
A. It's Time To Duel
思路
首先全是1的情况是不合法的,有两个0相连的情况也是不合法的,其他的情况都是不合法的
代码
void solve(){int n;cin>>n;vi a(n+10);bool f=false;for(int i=1;i<=n;i++){cin>>a[i];if(a[i]==0) f=true;}if(!f){cout<<"YES\n";return;}for(int i=1;i<n;i++){if(a[i]==0&&a[i+1]==0){cout<<"YES\n";return;}}cout<<"NO\n";
}
B. Slice to Survive
思路
最初位于(a,b)我们需要切一刀,这是必须的我们有4种情况,然后每次都贪心的跑到剩余方格的中间,再进行切割,最后发现总次数其实就是在已经切割的情况下,边长每次=(边长+1)/2直到等于1
最初的切一刀是不能贪心的我们无法贪心的求出哪个最多,只能枚举这四个情况
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;int f(int x,int y){int res=1;while(x!=1){res++;x=(x+1)/2;}while(y!=1){res++;y=(y+1)/2;}return res;
}void solve(){int n,m,a,b;cin>>n>>m>>a>>b;int ans=min({f(n,b),f(n,m-b+1),f(a,m),f(n-a+1,m)});cout<<ans<<"\n";
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}
C1. Hacking Numbers (Easy Version)
思路
首先我要提醒一点:在最后结尾输出 !后还要输入个1 这个也是硬控了我30分钟左右(被资本做局了)
首先我们肯定能想到我们需要将这个未知的数x转化成一个已知的数然后再由这个已知数x转化成n
对于此题的要求我们需要6步将x变为一个已知的数
走两遍digit这样这样数就变成了1-16的一个数(如果我们走三遍的话会变成1-9但是后面再操作的时候就不够了)
这样我们的x就变成了1-16,然后再进行(add -8)(add -4) (add -2) (add -1)类似于二分的思维
这样最后我们就把x变成了1
最后再mul n或add n-1将x变成n即可
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;int query(string s,int x){cout<<s<<" "<<x<<endl;int res;cin>>res;return res;
}
void solve(){int n;cin>>n;int res;cout<<"digit"<<endl;cin>>res;cout<<"digit"<<endl;cin>>res;query("add",-8);query("add",-4);query("add",-2);query("add",-1);query("mul",n);cout<<"!"<<endl;cin>>res;
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}
C2. Hacking Numbers (Medium Version)
思路
此题将上面的步数压缩到了4步,也就是说我们需要进行3步将x变成一个已知的数
将数*9之后两遍digit然后x就神奇地变成9了???
哦这原来与一个性质有关,各位数之和能被9整除时才能整除9
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;int query(string s,int x){cout<<s<<" "<<x<<endl;int res;cin>>res;return res;
}
void solve(){int n;cin>>n;int res;query("mul",9);cout<<"digit"<<endl;cin>>res;cout<<"digit"<<endl;cin>>res;query("add",n-9);cout<<"!"<<endl;cin>>res;
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}
C3. Hacking Numbers (Hard Version)
思路
感觉这题很难想到啊。反正我不看题解的解释是绝对想不到的,也算是增长了经验了
关于这个数*999999999之后再来一遍digit之后数就神奇地变成81了???
严格证明还是参考一下官方题解吧
最后还要注意特判一下n=81的时候
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;int query(string s,int x){cout<<s<<" "<<x<<endl;int res;cin>>res;return res;
}
void solve(){int n;cin>>n;int res;query("mul",999999999);cout<<"digit"<<endl;cin>>res;if(n!=81){query("add",n-81); }cout<<"!"<<endl;cin>>res;
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}
D. D/D/D
思路
我们发现如果走到一个节点之后我们可以消耗2的倍数步来重复回到此节,那么我们在处理a数组时我们只需要统计一下能走的最大偶数步和最大奇数步即可
然后我们跑一遍图用类似于最短路的解决办法记录每个节点走偶数步能到达的最短步数和奇数步能到达的最短
最后再比较一下能移动最大步数更新一下答案
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;void solve(){int n,m,l;cin>>n>>m>>l;vector<int> a(l+10);int s0=0; //存偶数总和int s1=0; //存奇数总和int mn1=inf; //存最小的奇数for(int i=1;i<=l;i++){cin>>a[i];if(a[i]%2==0) s0+=a[i];else{s1+=a[i];mn1=min(mn1,a[i]);}}//tmp用来存如果要求走偶数步奇数所能提供的贡献int tmp = (s1%2==0) ? s1:s1-mn1;if(s1==0) tmp=0;int step0=s0+tmp; //偶数最大步数//t用来存如果走奇数步奇数所能提供的贡献int t = (s1%2==0) ? s1-mn1:s1;if(s1==0) t=0;int step1=s0+t;if(t==0) step1=0; //奇数最大步数vector<vector<int>> e(n+1);for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}vector<vector<int>> dis(n+10,vector<int>(2,inf));//表示从1到达i顶点时走0/1 偶数步/奇数步的最小步数queue<pll> q;dis[1][0]=0;q.push({1,0});while(!q.empty()){auto [u,d]=q.front();q.pop();for(auto v:e[u]){if(dis[v][1-d]>dis[u][d]+1){dis[v][1-d]=dis[u][d]+1;q.push({v,1-d});}}}vector<int> ans(n+10);for(int i=1;i<=n;i++){if(step0>=dis[i][0]) ans[i]=1;if(step1>=dis[i][1]) ans[i]=1;}for(int i=1;i<=n;i++){cout<<ans[i];}cout<<"\n";}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;cin>>_;while(_--) solve();return 0;
}