ABC 365

赛时通过:A、B、C。

赛后补题:D、E。

A

依题判断即可。

#include<bits/stdc++.h>
using namespace std;
int y;
int main(){
	cin>>y;
	if(y%4!=0) cout<<365;
	if(y%4==0&&y%100!=0) cout<<366;
	if(y%100==0&&y%400!=0) cout<<365;
	if(y%400==0) cout<<366;
}

B

排序即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e2+5;
int n;
pair<int,int> a[N];

signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].first,a[i].second=i;
	sort(a+1,a+n+1);
	cout<<a[n-1].second;
	return 0;
}

C

显然 \(x\) 越大,总费用越大,具有单调性。二分即可求出最大的 \(x\)

当 $ \sum a_i > M$ 时,\(x\) 便可无限大。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+5;
int n,m,a[N];

bool check(int x){
	int s=0;
	for(int i=1;i<=n;i++) s+=min(x,a[i]);
	return s<=m;
}

signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	int s=0;
	for(int i=1;i<=n;i++) cin>>a[i],s+=a[i];
	if(s<=m) cout<<"infinite",exit(0);
	int l=0,r=m+1;
	while(l+1<r){
		int mid=(l+r)>>1;
		if(check(mid)) l=mid;
		else r=mid;
	}
	cout<<l;
	return 0;
}

D

首先贪心是错误的。详情见这份 Hack https://atcoder.jp/contests/abc365/editorial/10601 (https://atcoder.jp/contests/abc365/editorial/10601)。

然后考虑 dp。因为过于简单,所以具体细节见代码。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+5;
int n;
string s;
int dp[N][3];
//0/1/2:R/P/S
//R->S S->P P->R

signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>s,s="#"+s;
	if(s[1]=='R')
		dp[1][0]=0,
		dp[1][1]=1,
		dp[1][2]=-1e9;
	else if(s[1]=='P')
		dp[1][0]=-1e9,
		dp[1][1]=0,
		dp[1][2]=1;
	else
		dp[1][0]=1,
		dp[1][1]=-1e9,
		dp[1][2]=0;
	for(int i=2;i<=n;i++){
		if(s[i]=='R')
			dp[i][0]=max(dp[i-1][1],dp[i-1][2]),
			dp[i][1]=max(dp[i-1][0],dp[i-1][2])+1;
		else if(s[i]=='P')
			dp[i][1]=max(dp[i-1][0],dp[i-1][2]),
			dp[i][2]=max(dp[i-1][0],dp[i-1][1])+1;
		else
			dp[i][0]=max(dp[i-1][1],dp[i-1][2])+1,
			dp[i][2]=max(dp[i-1][0],dp[i-1][1]);
	}
	cout<<max({dp[n][0],dp[n][1],dp[n][2]});
}

E

灵茶八题 T3。

看到异或运算,考虑二进制拆位。

考虑异或的一个性质:

\[S_r \oplus S_{l-1} = \oplus ^ {r} _ {i=l} A_i \]

其中:

\[S_i=\oplus ^ {i} _ {j=1} A_j \]

(这是因为,\(S_r\)\(S_{l-1}\) 的相同部分会被消去)

于是,我们求出 \(S\) 数组(\(n+1\) 位),其中第 \(0\) 位是为了提取长度为 \(1\) 的子数组。

能提取出一个子数组,当且仅当 \(S_r\)\(S_{l-1}\) 的某一位的异或值为 \(1\),不然这俩的贡献就是 \(0\)

考虑二进制拆位。对于 \(S\) 数组中的每一位,只有两位分别是 \(0,1\) 时,才会有贡献。

于是我们统计出每一位中 \(1\) 的个数 \(x\),则 \(0\) 的个数即为 \(n+1-x\),通过乘法原理计算可得贡献即为 \((n+1-x) \times x\),再乘上 \(2^j\) 即为当前位的贡献,累加即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+5,M=31;
int n,ans;
int a[N],s[N];

signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i],s[i]=s[i-1]^a[i];
	}
	int ans=0;
    for(int j=0;j<31;j++){
        int cnt=0;
        for(int i=0;i<=n;i++) cnt+=s[i]>>j&1; 
		ans+=(cnt)*(n+1-cnt)*(1<<j);
    }
    for(int i=1;i<=n;i++) ans-=a[i];
    cout<<ans;
	return 0;
}
posted @ 2024-08-10 10:16  _XOFqwq  阅读(4)  评论(0编辑  收藏  举报