Div.3难度的cf感觉挺有好的,简单的都能开,稍微上一点强度就都不咋会写了.
首先来看签到题:Problem-A
给你一个整数 xx 。你需要找出最小的非负整数 yy ,使得数字 xx 和 yy 至少有一个共同的数位。换句话说,必须有一个十进制数 dd 同时出现在数字 xx 和数字 yy 的表示中。
输入
第一行包含一个整数 t ( 1 ≤ t ≤ 1000 ) - 测试用例的数量。
每个测试用例的第一行包含一个整数 x ( 1 ≤ x ≤ 1000 )。
输出
针对每个测试用例,输出一个整数 y 。- 满足条件的最小非负数。
对的,这是一道签到题,看样例就能找到规律:所有位数上的最大数值!
解法一:输入一个整数 不断除以10得到每一个数位上的数 然后更新最大值
解法二:直接输入一个字符串 然后遍历字符串找到最大值即可
解法三:还是输入一个字符串,然后用sort自动排序直接输出最大值
赛时代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define PII pair<int,int>
#define fi first
#define se second
void solve()
{
string s;
cin>>s;
int ans=1e18;
for(int i=0;i<s.size();i++)
{
ans = min(ans,(int)s[i]-'0');//使用比较函数的时候注意类型一致
}
cout<<ans<<endl;
}
signed main()
{
IOS
int T=1;
cin>>T;
while(T--) solve();
return 0;
}
然后就是第二题:Problem-B
这是一道比较简单的模拟题,遍历一遍数组即可,需要注意对num的维护!
赛时代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define PII pair<int,int>
#define fi first
#define se second
const int N = 1e5+10;
int a[N];
void solve()
{
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0,num=0;
for(int i=1;i<=n;i++)
{
if(a[i]==0) num++;
if(num==k)
{
ans++;
num=0;
i++;
}
else if(a[i]==1)
{
num=0;
}
}
cout<<ans<<endl;
}
signed main()
{
IOS
int T=1;
cin>>T;
while(T--) solve();
return 0;
}
第三题:Problem-C
你得到了 n 座塔,编号从 1 到 n 。塔楼 i 的高度为 hi 。在时间 0 ,你位于指数为 k 的塔上,当前水位为 1 。
每秒钟,水位上升 1 个单位。在任何时刻,如果水位严格大于您所在塔楼的高度,您就会死亡。
你有一个神奇的能力:在 x 时刻,你可以开始从塔楼 i 传送到塔楼 j ,需要 |hi−hj| 秒。也就是说,在 x+|hi−hj| 时刻之前,您将在塔楼 i ,而在 x+|hi−hj| 时刻,您将移动到塔楼 j 。您可以在刚刚到达塔楼 j 的同一时刻开始新的传送。
例如,如果 n=k=4,h=[4,4,4,2],那么如果您在0时刻从塔楼 4 开始传送到塔楼 1,移动过程如下:
请注意,如果塔楼 1 的高度为 5 ,您将无法立即传送到塔楼,因为您将在 2 时刻被淹没。
您的目标是在被水淹没之前到达高度最大的塔楼。
确定这是否可行。
这道题是一个小思维题,你可以一致传送,直到你到达了最高的楼,而你传送需要消耗时间,你需要消耗的时间就是两栋楼的高度差,例如:你可以用1秒的时间从高度为3的楼传送到高度为4 的楼但是在这1秒内,水位会上升1格,所以:你花费了多少时间传送,水位就会上升多少,只要你成功传送到了另一栋楼,你和水位的相对位置是不变的!而你如果没有传送到另一栋楼,就直接可以结束了,只需要对楼的高度进行排序,然后从第一个大于目前高度的这栋楼的开始往后遍历,只要两者之间的高度差小于初始时人和水位的高度差就说明这栋楼他就要结束了!反之就能成功传送!
赛时代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5+10;
int a[N];
void solve()
{
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int now = a[k];
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
if(a[i]>now)
{
if(a[i] - a[i-1] > now)
{
cout<<"NO"<<endl;
return ;
}
}
}
cout<<"YES"<<endl;
}
signed main()
{
IOS
int T = 1;
cin >> T;
while(T--) solve();
return 0;
}
第四题:Problem-D
首先要知道的是,最终的答案一定不会小于开始时的金币的数量,那么我们只需要考虑每一个能够获得比当前的金币数量多的赌场即可,这就用到了自定义排序, 对这几个赌场按照最终能获得的金币来从小到大进行排序,然后不断更新现在的金币数量直到最后一个遍历完即可!
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
const int N = 1e5+10;
struct aaa
{
int l,r,v;
}a[N];
bool cmp(aaa x,aaa y)
{
return x.v<y.v;
}
void solve()
{
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r>>a[i].v;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(a[i].v > k)
if(k>=a[i].l && k<=a[i].r) k=a[i].v;
}
cout<<k<<endl;
}
signed main()
{
IOS
int T = 1;
cin >> T;
while(T--) solve();
return 0;
}
第五题:Problem-E
解题思路
- 首尾一致性检查:首先,
p
数组的最后一个元素p[n]
应该等于s
数组的第一个元素s[1]
,因为它们都代表整个数组a
的 GCD。如果不相等,直接判定不存在这样的数组a
。 - 前缀数组单调性检查:前缀 GCD 数组
p
应该是非递增的。因为随着i
增大,前缀包含的元素增多,GCD 要么不变,要么变小。如果p
数组后一个元素比前一个大,就不符合逻辑,判定不存在。 - 后缀数组单调性检查:后缀 GCD 数组
s
应该是非递减的。因为随着i
增大,后缀包含的元素减少(从后往前看是包含元素增多方向),GCD 要么不变,要么变大。如果s
数组后一个元素比前一个小,判定不存在。 - 构造验证:对于每个位置
i
,假设a[i]
是p[i]
和s[i]
的最小公倍数(lcm
)。然后需要验证:- 对于
i > 1
,gcd(p[i - 1], a[i])
应该等于p[i]
,确保前缀 GCD 的递推关系正确。 - 对于
i < n
,gcd(a[i], s[i + 1])
应该等于s[i]
,确保后缀 GCD 的递推关系正确。
- 对于
对于解题思路1 2 3 应该没啥大问题,主要就出现在4这里,我来解释一下:
因为s[i]是a[i]及之前所有的数的gcd, 那么s[i]一定是a[i]的一个因数(因为求了gcd运算之后的值一定是里面所有元素共同的因数,当然也就是a[i]的因数了!)后缀gcd数组同样如此,跟前缀没啥大的区别t[i]也是a[i]及以后所有元素的因数当然也就是a[i]的因数了,所以a[i]至少为s[i]和t[i]的最小公倍数!
// *********************************************
// Problem: E. G-C-D, Unlucky!
// Contest: Codeforces - Codeforces Round 1037 (Div. 3)
// URL: https://codeforces.com/contest/2126/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// *********************************************
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int N=1e5+5;
int s[N],t[N];
int lcm(int x,int y)
{
int g=__gcd(x, y);
int z=x/g*y;
return z;
}
void slove(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) cin>>t[i];
if(s[n]!=t[1])//首尾判断
{
cout<<"NO"<<endl;
return ;
}
for(int i=2;i<=n;i++)//前缀GCD单调非递增性检查
{
if(s[i-1]<s[i])
{
cout<<"NO"<<endl;
return;
}
}
for(int i=2;i<=n;i++)//后缀GCD单调非递减性检查
{
if(t[i-1]>t[i])
{
cout<<"NO"<<endl;
return;
}
}
for(int i=1;i<=n;i++)//内部元素的构造合理性检查
{
int ai=lcm(s[i], t[i]);//因为这个数既要是s[i]的倍数又要是t[i]的倍数
//换句话说s[i]是a[i]的一个因数 同时t[i]也得是a[i]的因数
if(i>1)
{
if(__gcd(s[i-1], ai)!=s[i])
{
cout<<"NO"<<endl;
return ;
}
}
if(i<n)
{
if(__gcd(ai, t[i+1])!=t[i])
{
cout<<"NO"<<endl;
return ;
}
}
}
cout<<"YES"<<endl;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T=1;
cin>>T;
while(T--)
slove();
return 0;
}
这次的比赛我就先补到这里。是因为我不想补吗?等我有能力了我自然会去AK的!