AtCoder Beginner Contest 365(A~E)

mj666發表於2024-08-06

AtCoder Beginner Contest 365(A~E)

A

問題陳述

給你一個介於 \(1583\)\(2023\) 之間的整數 \(Y\)

求公曆 \(Y\) 年的天數。

在給定的範圍內, \(Y\) 年的天數如下:

  • 如果 \(Y\) 不是 \(4\) 的倍數,則為 \(365\) 天;
  • 如果 \(Y\)\(4\) 的倍數,但不是 \(100\) 的倍數,則為 \(366\) 天;
  • 如果 \(Y\)\(100\) 的倍數,但不是 \(400\) 的倍數,則為 \(365\) 天;
  • 如果 \(Y\)\(400\) 的倍數,則為 \(366\) 天。

Solution

#include <bits/stdc++.h>
using namespace std;
int n;
int main(){
	scanf("%d",&n);
	if(n%400==0 || (n%4==0 && n%100!=0)) printf("366");
	else printf("365");
	return 0;
}

B

問題陳述

給你一個長度為 \(N\) 的整數序列 \(A=(A_1,\ldots,A_N)\)。這裡, 都 \(A=(A_1,\ldots,A_N)\) 是不同的。

\(A\) 中,哪個元素是第二大元素?

Solution

維護最大值和第二大的值即可。時間複雜度 \(O(n)\)

#include <bits/stdc++.h>
using namespace std;
const int N=105;
int n,a[N],max1,max2;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		if(a[i]>max1) max2=max1,max1=a[i];
		else if(a[i]>max2) max2=a[i];
	}
	for(int i=1;i<=n;++i){
		if(a[i]==max2){
			printf("%d",i);
			return 0;
		}
	}
	return 0;
}

C

問題陳述

\(N\) 人參加一項活動, \(i\) /人的交通費用是 \(A_i\) 日元。

活動組織者高橋(Takahashi)決定設定交通補貼的最高限額為 \(x\)\(i\) 人的補貼為 \(\min(x, A_i)\) 日元。這裡, \(x\) 必須是一個非負整數。

高橋的預算為 \(M\) 日元,他希望所有 \(N\) 人的交通補貼總額最多為 \(M\) 日元,那麼補貼限額 \(x\) 的最大可能值是多少?

如果補貼限額可以無限大,請報告。

Solution

若補貼限額可以無限大,則 \(\sum_{i=1}^nA_i\le M\)

如果不可以無限大, \(x\) 一定越小越好,具有單調性,考慮二分。

時間複雜度 \(O(nlogn)\)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N=2e5+5;
int n,a[N];
LL m,ans,L=1,R=2e14,sum[N];
bool chk(LL x){
	int pos=lower_bound(a+1,a+n+1,x)-a-1;
	return x*(n-pos)+sum[pos]<=m;
}
int main(){
	scanf("%d %lld",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;++i){
		sum[i]=sum[i-1]+a[i];
	}
	while(L<=R){
		LL mid=L+R>>1;
		if(chk(mid)) L=mid+1,ans=mid;
		else R=mid-1;
	}
	if(ans==2e14) printf("infinite");
	else printf("%lld",ans);
	return 0;
}

D

問題陳述

高橋和青木玩了 \(N\) 次石頭剪刀布。注:在這個遊戲中,石頭贏剪刀,剪刀贏紙,紙贏石頭。

青木的動作由長度為 \(N\) 的字串 \(S\) 表示,字串由 "R"、"P "和 "S "組成。 \(S\)\(i\) -th字元表示青木在 \(i\) -th對局中的棋步:R "表示 "石頭","P "表示 "紙","S "表示 "剪刀"。

高橋的棋步滿足以下條件:

  • 高橋從未輸給過青木。
  • 對於 \(i=1,2,\ldots,N-1\) ,高橋在 \(i\) 對局中的棋步與他在 \((i+1)\) 對局中的棋步不同。

請確定高橋的最大勝局數。

可以保證存在一個滿足這些條件的高橋的下棋順序。

Solution

考慮動態規劃。設 \(dp_{i,0}\) 表示第 \(i\) 局平局時的最大勝局數, \(dp_{i,1}\) 表示第 \(i\) 局獲勝時的最大勝局數, \(ans_i\) 表示贏 \(S_i\) 的棋步。

\(S_i\ne S_{i-1}\) ,則 \(dp_{i,0}=\max(dp_{i,0},dp_{i-1,0})\)

\(S_i \ne ans_{i-1}\) ,則 \(dp_{i,0}=max(dp_{i,0},dp_{i-1,1})\)

\(ans_i\ne S_{i-1}\) ,則 \(dp_{i,1}=max(dp_{i,1},dp_{i-1,0}+1)\)

\(ans_i\ne ans_{i-1}\) ,則 \(dp_{i,1}=max(dp_{i,1},dp_{i-1,1}+1)\)

時間複雜度 \(O(n)\)

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,dp[N][2];
char s[N],ans[N];
int main(){
	scanf("%d %s",&n,s+1);
	for(int i=1;i<=n;++i){
		if(s[i]=='R') ans[i]='P';
		else if(s[i]=='P') ans[i]='S';
		else ans[i]='R';
	}
	dp[1][1]=1;//1表示贏第i局
	for(int i=2;i<=n;++i){
		if(s[i]!=s[i-1]) dp[i][0]=max(dp[i][0],dp[i-1][0]);
		if(s[i]!=ans[i-1]) dp[i][0]=max(dp[i][0],dp[i-1][1]);
		if(ans[i]!=s[i-1]) dp[i][1]=max(dp[i][1],dp[i-1][0]+1);
		if(ans[i]!=ans[i-1]) dp[i][1]=max(dp[i][1],dp[i-1][1]+1);
	}
	printf("%d",max(dp[n][0],dp[n][1]));
	return 0;
}

E

問題陳述

給你一個長度為 \(N\) 的整數序列 \(A=(A_1,\ldots,A_N)\) 。求以下表示式的值:

\[\displaystyle \sum_{i=1}^{N-1}\sum_{j=i+1}^N (A_i \oplus A_{i+1}\oplus \ldots \oplus A _j) \]

關於位向 XOR 的說明 非負整數 \(A\)\(B\) 的位向 XOR 定義如下,記為 \(A \oplus B\)

  • \(A \oplus B\) 的二進位制表示中,當且僅當 \(A\)\(B\) 的二進位制表示中 \(2^k\) 位上的數字是 \(1\) 時, \(2^k\) ( \(k \geq 0\) )位上的數字是 \(1\) ;否則,它是 \(0\)

例如, \(3 \oplus 5 = 6\) (二進位制: \(011 \oplus 101 = 110\) )。
一般來說, \(k\) 個整數 \(p_1, \dots, p_k\) 的位元 XOR 定義為 \((\cdots ((p_1 \oplus p_2) \oplus p_3) \oplus \cdots \oplus p_k)\) 。可以證明這與 \(p_ 1, \dots, p_k\) 的階數無關。

Solution

對於區間 \([L,R]\) ,異或和的二進位制結果的第 \(i\) 位為 \(1\) 的充要條件是 \(A_L\)\(A_R\) 的所有數中第 \(i\) 位是 \(1\) 的數有奇數個。

\(cnt_{i,j}\) 表示前 \(i\) 個數中第 \(j\) 位是 \(1\) 的數的個數,那麼\(A_L\)\(A_R\) 的所有數中第 \(i\) 位是 \(1\) 的數的個數可以表示為

\[cnt_{R,i}-cnt_{L-1,i} \]

列舉右端點 \(R\) ,若 \(L\) 滿足 \(cnt_{L-1,i}\)\(cnt_{R,i}\) 奇偶性不同,則 \(2^i\) 對答案有貢獻。對於每個 \(R\) ,只需記錄 \(L\) 的個數即可。

時間複雜度 \(O(33n)\)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+5;
int n,a[N],cnt[N][40];
LL ans,cnt0,cnt1,sum;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		sum+=a[i];
		for(int j=0;j<=32;++j){
			cnt[i][j]=cnt[i-1][j];
			if(a[i]&(1ll<<j)) cnt[i][j]++;
			cnt[i][j]%=2;
		}
	}
	// for(int i=1;i<=n;++i){
	// 	for(int j=0;j<=3;++j){
	// 		printf("%d ",cnt[i][j]);
	// 	}
	// 	printf("\n");
	// }
	for(int i=0;i<=32;++i){
		cnt0=1,cnt1=0;		//cnt0=1將左端點為1的加上
		for(int j=1;j<=n;++j){
			if(cnt[j][i]==1){
				cnt1++;
				ans+=cnt0*(1ll<<i);
			}
			else{
				cnt0++;
				ans+=cnt1*(1ll<<i);
			}
		}
	}
	printf("%lld",ans-sum);
	return 0;
}

相關文章