首页 > 其他分享 >AtCoder Beginner Contest 365(A~E)

AtCoder Beginner Contest 365(A~E)

时间:2024-08-06 12:27:42浏览次数:7  
标签:AtCoder cnt Beginner int 高桥 ans oplus 365 dp

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;
}

标签:AtCoder,cnt,Beginner,int,高桥,ans,oplus,365,dp
From: https://www.cnblogs.com/mj666/p/18344916

相关文章

  • 【做题笔记】板刷 AtCoder
    [ABC364D]K-thNearest很好想的题目。首先可以考虑到答案具有单调性,所以对于每一次询问用二分处理即可。然后考虑如何判合法。我们需要找到所有\(a_i-b\)中\(\lex\)且\(\ge-x\)的个数。可以现将\(a_i\)排好序,最后用两个二分统计个数看是否\(\gek\)即可。时间复......
  • AtCoder Beginner Contest 365(4/7)
    比赛链接:https://atcoder.jp/contests/abc365solve:ABC开头:感觉好久没打abc了,这场被D单防了qwq,该好好练练dp了A.LeapYear思路:签到题,闰年判断代码:#include<bits/stdc++.h>usingi64=longlong;voidsolve(){intn;std::cin>>n;if(n%400==0){......
  • Atcoder ABC299 E-G
    AtcoderABC299E-GE-NearestBlackVertex链接:E-NearestBlackVertex(atcoder.jp)简要题意:问题陈述给你一个简单连接的无向图,有\(N\)个顶点和\(M\)条边(简单图不包含自循环和多条边)。在\(i=1,2,\ldots,M\)中,\(i\)-th边双向连接顶点\(u_i\)和......
  • AtCoder Beginner Contest 365
    AtCoderBeginnerContest365A-LeapYear给出年份,判断这一年有多少天闰年条件已经给出,逐条判断模拟即可。#include<iostream>usingnamespacestd;intmain(){inty;cin>>y;if(y%400==0||y%4==0&&y%100!=0)cout<<366<<endl;else......
  • AtCoder Beginner Contest 365
    F-TakahashionGrid用线段树上的节点维护一下\((l,r,c)\),如果\(c\)为\(-1\):\(l,r\)表示这一段区间内\([l,r]\)的交。如果\(c\ne-1\),\(l,r\)表示这一段第一次上下界相等的时候的位置为\(l\),合并后走出来的位置为\(r\),然后转折的步数为\(c\)。然后这玩意可以合并......
  • ABC365
    Alink题目已经说的很明白了,判断即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;inty;signedmain(){ cin>>y; if(y%4!=0)cout<<365; elseif(y%4==0&&y%100!=0)cout<<366; elseif(y%100==0&&y%400!......
  • ABC365
    A.LeapYear模拟代码实现importcalendary=int(input())ifcalendar.isleap(y):print(366)else:print(365)B.SecondBest模拟代码实现n=int(input())a=list(map(int,input().split()))print(a.index(sorted(a)[-2])+1)C.TransportationEx......
  • 【A~E】AtCoder Beginner Contest 365
    A-LeapYear题目大意给定\(n\),求第\(n\)年的天数(\(365\)或\(366\))。思路显然地,我们需要判断这个是否为闰年。如果\(n\)不能被\(4\)整除,那么不是闰年。如果\(n\)可以被\(400\)整除,那么是闰年。如果\(n\)不可以被\(100\)整除但是可以被\(4\)整除,那么是......
  • AtCoder Beginner Contest 365 补题记录(A~E,G)
    Perf2000+,但是补不回来上场超低的Rating/llA#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;signedmain(){intn;cin>>n;if(n%400==0)cout<<"366\n";elseif(n%100==0)cout<<"365\n";......
  • AtCoder Beginner Contest 365 随笔
    擦,F假了A判断闰年B输出次大值的下标用pair排序后即可C给定一个数组\(A_n\)和整数\(M\),尝试找到一个最大的\(m\),使得:\[\sum_{i=1}^n\min(A_i,m)\leM\]不等号左边显然随着\(m\)的增大而增大,所以可以二分一个\(m\),然后判断即可D两个人玩\(n\)局剪刀石头布......