【A~E】AtCoder Beginner Contest 365
A - Leap Year
题目大意
给定
思路
显然地,我们需要判断这个是否为闰年。
如果
如果
如果
否则就不是闰年。
很简单。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n;cin>>n;
if(n%4!=0){
cout<<365;
}
else if(n%400==0){
cout<<366;
}
else if((n%100!=0)&&n%4==0){
cout<<366;
}
else cout<<365<<endl;
return 0;
}
B - Second Best
题目大意
给定
思路
打擂。记目前最大值为
如果
如果
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n;cin>>n;
vector<int>a(n+1);
for(int i=1;i<=n;i++)
cin>>a[i];
int ans1=a[1],ans2=0;
int pos1=1,pos2=0;
for(int i=2;i<=n;i++){
if(a[i]>ans1){
ans2=ans1;
pos2=pos1;
ans1=a[i];
pos1=i;
}
else if(a[i]>ans2){
ans2=a[i];
pos2=i;
}
}
cout<<pos2<<endl;
return 0;
}
C - Transportation Expenses
题目大意
给定
思路
很板的二分答案。
首先考虑无穷大的答案。可以先计算序列的总和和
如果不是无穷大呢?可以试着枚举一个
考虑二分一个
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[200005],ans=-1e17;
bool check(int x){
int res=0;
for(int i=1;i<=n;i++)
res+=min(a[i],x);
return (res<=m);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
if(check(1e17)){
cout<<"infinite"<<endl;
return 0;
}
int l=0,r=m;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans<<endl;
return 0;
}
D - AtCoder Janken 3
题目大意
两个人玩石头剪刀布,已知
思路
因为发现
设
显然发现通过判断当前局和上一局的平局和胜利的出招是否相同来进行转移。
具体见代码。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,f[200001][2]={0};
string s;
char lp,lwin;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>s;
f[0][0]=0,f[0][1]=1;
if(s[0]=='S')lwin='R',lp='S';
else if(s[0]=='R')lwin='P',lp='R';
else lwin='S',lp='P';
for(int i=1;i<n;i++){
char p,win;
if(s[i]=='S')win='R',p='S';
else if(s[i]=='R')win='P',p='R';
else win='S',p='P';
if(p!=lp)f[i][0]=max(f[i-1][0],f[i][0]);
if(p!=lwin)f[i][0]=max(f[i-1][1],f[i][0]);
if(win!=lp)f[i][1]=max(f[i-1][0]+1,f[i][1]);
if(win!=lwin)f[i][1]=max(f[i-1][1]+1,f[i][1]);
lp=p,lwin=win;
}
cout<<max(f[n-1][0],f[n-1][1])<<endl;
return 0;
}
E - Xor Sigma Problem
题目大意
给定
思路
考虑一下这道题的弱化版:求序列中两两异或的总和,也就是求
不难发现,正常求是需要
也就是把每一个数都拆成二进制位,比如对于
可以发现,每一位的贡献其实都是这一位上两两异或为
也就是说,第一位会产生
以此类推,每一位的贡献分别为
那么乘上每一位的权重,可以得出答案为:
再来考虑一下原问题,不难发现我们可以预处理出一个异或前缀
也就是说,我们目前得到了所有的区间的异或值,不难看出原题的答案就是:
这个式子看起来挺复杂吧?
其实再深入思考一下就可以发现其实中间的那一大串(
也就是说,我们可以根据
具体见代码。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int ans[20]={0};
int b[200001];
int sum[200001]={0};
long long res=0;
int n,a,i,len,mx=-1;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)sum[i]=sum[i-1]^b[i];
for(i=1;i<=n;i++){
a=sum[i];
len=0;
while(a){
len++;
if(a&1)ans[len]++;
a=a>>1;
}
mx=max(mx,len);
}
for(i=1;i<=mx;i++)
res+=(1ll<<(i-1))*ans[i]*(n-ans[i]);
for(int i=1;i<=n;i++)
res+=sum[i],res-=b[i];
cout<<res;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现