牛客小白月赛110
A
模拟
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
cin>>n;
int cnt=0;
while(n>500){
++cnt;
n-=500;
}
char c='A'+cnt;
string s;
while(n){
s+=n%10+'0';
n/=10;
}
while(s.size()<3){
s=s+'0';
}
reverse(s.begin(),s.end());
cout<<c<<s<<endl;
return 0;
}
B
按照题意
点击查看代码
#include<bits/stdc++.h>
using namespace std;
string n,m;
string ans;
int main(){
cin>>n>>m;
for(int i=0;i<8;++i)
if(n[i]==m[i]) ans+='g';
else{
if(n.find(m[i])!=-1) ans+='y';
else ans+='r';
}
cout<<ans<<endl;
if(ans.find('y')==-1) cout<<"congratulations"<<endl;
else cout<<"defeat"<<endl;
return 0;
}
C
这种题比较典
通常这种题,让你在满足条件的数组成的数列中,找出第k大的数,而且,这些数单调递增,很适合二分查找
以此题为例:
满足条件:
奇数同时,满足以下之一条件
1.以5为结尾的数
$ 5,15,25,......(a_n=5+(n-1)10 3,9,15,21,......(b_n=3+(n-1)6$
但敏锐地发现,15重复了,再我们确定第k大时,需要剔除重复以免误算
这里就可以用容斥定理
此时我们验证数m
(利用上述数列公式,推出小于m的个数)
以5结尾的奇数
3的倍数的奇数
满足上述条件的奇数
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int t;
ll k;
bool check(ll x){
//分别表示,满足“各个数位相加的和是3的倍数”
//以5结尾
//同时满足上述两个条件的个数
ll a=(x+3)/6,b=(x+5)/10,c=(x+15)/30;
if(a+b-c<k) return 1;
return 0;
}
void solve(){
ll l=3,r=4385714285;
cin>>k;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid)) l=mid+1;
else r=mid-1;
}
cout<<l<<"\n";
return ;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
D
提示很明显,长期主义者就是DP,短期主义就是贪心
而这样的选择方式,类似于区间DP
我们定义是长期主义者,选择剩下区间[l,r]时最大的收益
按照区间DP定义,从区间为1的长度开始转移,所以这个题的DP其实是这个题博弈的逆过程
初始状态f[i][i]=n&1?0:a[i]
- 如果区间长度是奇数,最后选择的是贪心,所以f[i][i]就是0
- 否则,
状态转移看代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int l,r;
const int maxn=1e3+10;
int f[maxn][maxn];
int n;
int a[maxn];
ll sum=0;
int main(){
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i],sum+=a[i];
for(int i=1;i<=n;++i) f[i][i]=n&1?0:a[i];//因为是奇数,所以最后选到i时是长期为0
for(int i=2;i<=n;++i){
for(int l=1;l+i-1<=n;++l){
int r=l+i-1;
if((n-i)&1) f[l][r]=max(a[l]+f[l+1][r],a[r]+f[l][r-1]);//此时区间长度是n-i,所以是长期主义者选择
else f[l][r]=a[l]>=a[r]?f[l+1][r]:f[l][r-1];//贪心选择
}
}
cout<<sum-f[1][n]<<" "<<f[1][n]<<endl;//答案就很容易得到了
return 0;
}
E
对于一个数组,只有下标或者|,才能交换
所以我们直接想,如果一个数,能同时与两个其他的数交换,那么这三个都能交换,更抽象地想,能交换就说明有关系,就能抽象成图,能交换形成集合,于是可以用并查集记录可以交换的
进一步思考,既然交换后有序,那么排序后的数组和原数组的集合应该相同,也就是连通性相同,所以我们需要各自记录连通性,验证是否完全相同就行
而此时我们很容易发现无论是否排序,|都是恒成立的,所以我们可以直接将满足该条件的形成一个并查集
只需要验证也是一定连通的,所以只需要用一个集合set记录下标相差为k的,将其连通
具体实现看代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,k;
int a[maxn],b[maxn];
int f[maxn];
map<int,int>mp;
multiset<int>x[maxn],y[maxn];
int find(int x){
if(x!=f[x]) f[x]=find(f[x]);
return f[x];
}
void solve(){
cin>>n>>k;
for(int i=1;i<=n;++i){
f[i]=i;
cin>>a[i];
b[i]=a[i];
mp[a[i]]=i;
}
for(int i=1;i<=n;++i){
if(mp[a[i]+k])
f[find(mp[a[i]+k])]=find(mp[a[i]]);//值相差为k可以交换,连通
}
for(int i=1;i<=n;++i)
x[i%k].insert(find(i));//下标相差为k可以交换,加入连通块
sort(b+1,b+1+n);
for(int i=1;i<=n;++i)//有序数组的连通
y[i%k].insert(find(mp[b[i]]));//下标相差为k的,加入b[i]所在在原数组中的位置的连通块
//这里其实是一个反证法,假设,这两个集合是一样的,那么b[i]在原数组的下标所在的连通块,也一定与原数组所在的连通块相同,否则则不能转换
for(int i=0;i<min(n,k);++i)
if(x[i]!=y[i]){//有序序列的连通性和无序的相同才能转换
puts("No");
return ;
}
puts("Yes");
}
int main(){
cin.tie(0);cout.tie(0);
solve();
return 0;
}
F
显然直接地找出每一对是超时的,而注意,问题问的是是否存在,
我们稍加转换,也就是用前缀积转化
于是
,
这里眼熟的小伙伴应该知道,可以用逆元:
,
所以根据这个表达式,当我们固定右端点时,若存在一个端点,使得上式成立,那我们就应该修改,最简单的方法就是修改为,因为这样就不用担心后面的值累乘之后等于,这样次数同时也最少
而当我们枚举到时,前面已经求出来了,所以这里就问题
就只需要验证是否存在就行
如果在思考,你会发现如果,那么就不能修改为0,此时就要就数列中所有的数修改为不为0
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,p,x;
const int maxn=1e5+10;
ll a[maxn];
ll quick_pow(ll a,ll b){
ll base=a;
ll ans=1;
while(b){
if(b&1) ans=ans*base%p;
base=base*base%p;
b>>=1;
}
return ans%p;
}
void solve(){
cin>>n>>p>>x;
for(int i=1;i<=n;++i) cin>>a[i];
if(x==0){
for(int i=1;i<=n;++i)
if(a[i]==0) a[i]=1;
}
else {
ll t=1;//前缀积
ll inv=1;//逆元
set<ll> s;
for(int i=1;i<=n;++i){
if(a[i]==0){
t=inv=1;
s.clear();
}
else {
s.insert(inv);
t=t*a[i]%p;
inv=inv*quick_pow(a[i],p-2)%p;
ll check=inv*x%p;
if(s.count(check)){
a[i]=0;
inv=t=1;
s.clear();
}
}
}
}
for(int i=1;i<=n;++i) cout<<a[i]<<" ";
puts("");
return ;
}
int main(){
int t=1;
while(t--) solve();
return 0;
}
本文作者:归游
本文链接:https://www.cnblogs.com/guiyou/p/18717375
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步