首页 > 其他分享 >【A~E】AtCoder Beginner Contest 365

【A~E】AtCoder Beginner Contest 365

时间:2024-08-03 22:40:41浏览次数:10  
标签:AtCoder cout Beginner int sum long 异或 oplus 365

A - Leap Year

题目大意

给定 \(n\),求第 \(n\) 年的天数(\(365\) 或 \(366\))。

思路

显然地,我们需要判断这个是否为闰年。

如果 \(n\) 不能被 \(4\) 整除,那么不是闰年。

如果 \(n\) 可以被 \(400\) 整除,那么是闰年。

如果 \(n\) 不可以被 \(100\) 整除但是可以被 \(4\) 整除,那么是闰年。

否则就不是闰年。

很简单。

代码

#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

题目大意

给定 \(\{a_n\}\),求次大值的位置。

思路

打擂。记目前最大值为 \(max\),目前次大值为 \(cmax\)。

如果 \(a_i>max\),那么把 \(cmax\) 更新为 \(max\),把 \(max\) 更新为 \(a_i\),同时记录位置。

如果 \(a_i<max\) 并且 \(a_i>cmax\),那么把 \(cmax\) 更新为 \(a_i\),同时记录位置。

代码

#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

题目大意

给定 \(\{A_N\}\),要求 \(\sum\min\{A_i,x\}\le M\),求最大值 \(x\)(可能为无穷大)。

思路

很板的二分答案。

首先考虑无穷大的答案。可以先计算序列的总和和 \(M\) 比较,如果这个都小于等于 \(M\),那么肯定答案是无穷大。

如果不是无穷大呢?可以试着枚举一个 \(x\),然后对于每一个 \(x\) 判断是否满足题目条件,然后记录最大的 \(x\),时间复杂度 \(O(NM)\)。

考虑二分一个 \(x\) 然后来判断,题目要求 \(x\) 的最大值,可以发现若此时的 \(x\) 为最大,那么对于每一个 \(k\le x\) 都可以满足题目条件,而对于每一个 \(k\ge x\) 都不能满足题目条件,满足单调性,写二分答案,时间复杂度 \(O(N\log M)\)。

代码

#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

题目大意

两个人玩石头剪刀布,已知 \(A\) 的出招顺序,而且 \(B\) 从来没有输给 \(A\),而且 \(B\) 相邻两次的出招是不一样的(比如这次 \(B\) 出了石头,那么他下一次就不能出石头),求 \(B\) 最多可以赢多少局。

思路

因为发现 \(B\) 出招的限制条件只和前一次和后一次的有关,所以这个问题显然满足无后效性,考虑 DP。

设 \(f_{i,0/1}\) 表示已经过了 \(i\) 局并且第 \(i\) 局 \(B\) 与 \(A\) 平局或赢(取 \(0\) 时两人平局,取 \(1\) 时 \(B\) 赢)时的最大胜场数。

显然发现通过判断当前局和上一局的平局和胜利的出招是否相同来进行转移。

具体见代码。

代码

#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

题目大意

给定 \(\{A_N\}\),求 \(\begin{aligned}\sum_{i=1}^{N-1}\sum_{j=i+1}^NA_i\oplus A_{i+1}\oplus\cdots\oplus A_j\end{aligned}\)。

思路

考虑一下这道题的弱化版:求序列中两两异或的总和,也就是求 \(\begin{aligned}\sum_{i=1}^{N-1}\sum_{j=i+1}^NA_i\oplus A_j\end{aligned}\)。

不难发现,正常求是需要 \(O(N^2)\) 的复杂度,考虑拆位。

也就是把每一个数都拆成二进制位,比如对于 \(A=\{2,3,5,8\}\),那么拆位之后就是:

\[2 : 0\ 0\ 1\ 0 \]

\[3 : 0\ 0\ 1\ 1 \]

\[5 : 0\ 1\ 0\ 1 \]

\[8 : 1\ 0\ 0\ 0 \]

可以发现,每一位的贡献其实都是这一位上两两异或为 \(1\) 的贡献。

也就是说,第一位会产生 \(3\) 的贡献(\(3\) 个 \(0\) 和 \(1\) 个 \(1\))。

以此类推,每一位的贡献分别为 \(3\),\(3\),\(4\),\(4\)。

那么乘上每一位的权重,可以得出答案为:

\[3\times2^3+3\times2^2+4\times2^1+4\times2^0=48 \]

再来考虑一下原问题,不难发现我们可以预处理出一个异或前缀 \(s\),也就是 \(s_i=s_{i-1}\oplus A_i\),那么类似前缀和,根据异或的自反性质,区间 \([l,r]\) 的异或为 \(s_r\oplus s_{l-1}\)。

也就是说,我们目前得到了所有的区间的异或值,不难看出原题的答案就是:

\[\begin{aligned}\sum^{N}_{i=1}s_i+\sum^{N}_{i=2}{s_i\oplus s_1}+\cdots+\sum^{N}_{i=N-1}{s_i\oplus s_{N-2}}-\sum^N_{i=1}A_i\end{aligned} \]

这个式子看起来挺复杂吧?

其实再深入思考一下就可以发现其实中间的那一大串(\(\begin{aligned}\sum^{N}_{i=2}{s_i\oplus s_1}+\cdots+\sum^{N}_{i=N-1}{s_i\oplus s_{N-2}}\end{aligned}\))拆开来看,其实就是 \(s_1\) 到 \(s_N\) 的两两异或!

也就是说,我们可以根据 \(s_i\) 来重新建一个序列,求完了这个序列的两两异或和之后再加上 \(\sum s_i\),然后因为原题中没有包含 \(A_i\) 的情况,所以还要再减去 \(\sum A_i\)。

具体见代码。

代码

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

标签:AtCoder,cout,Beginner,int,sum,long,异或,oplus,365
From: https://www.cnblogs.com/snapyust/p/18341238

相关文章

  • 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\)局剪刀石头布......
  • ABC365(A-D)未补
    A-LeapYear(模拟)题意:给定一个数字n,如果n不是4的倍数,输出365;如果n是4的倍数但不是100的倍数,输出366;如果n是100的倍数但不是400的倍数,输出365;如果n是400的倍数,输出366分析:模拟题目即可代码:#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;......
  • 如何通过PowerShell批量修改O365用户的office phone属性值
    我的博客园:https://www.cnblogs.com/CQman/如何通过PowerShell批量修改O365用户的officephone属性值?需求信息: 组织中的O365用户在创建时,已手动录入了办公电话(Officephone),现在需要在办公电话前面加上统一的数字,如“0571-0985”,以批量的方式统一修改。备注:O365用户的Offic......
  • Atcoder ABC298 D-F
    AtcoderABC298D-FD-WritingaNumeral链接:D-WritingaNumeral(atcoder.jp)简要题意:问题陈述我们有一个字符串\(S\)。初始值为\(S=\)1.按以下格式依次处理\(Q\)查询。1x:在\(S\)的末尾添加一个数字\(x\)。2:删除\(S\)开头的数字。3:以十进制形......
  • 每日一题——A - Max/Min AtCoder - abc356_e
    1.题目大意:枚举两个数的Max/Min向下取整之和。2.思路:一开始并没有想时间复杂度问题发现通过sort()排序来遍历每个最小值Min和后面最大值的和就是题目答案。你会发现仍然有问题,那就是取整的问题你就必须要优化然后发现很明显超时了。现在我们来换一个角度思考。搭配前缀和嘛。为......
  • Atcoder ABC297 E-G
    AtcoderABC297E-GE-KthTakoyakiSet链接:E-KthTakoyakiSet简要题意:问题陈述有\(N\)种章鱼烧出售。一个\(i\)-种的章鱼烧售价为\(A_i\)日元。高桥总共至少会买一个章鱼烧。他可以购买多个同类章鱼烧。求高桥可能支付的\(K\)个最低价格。在这里,如果有多......
  • Dynamics 365 online查询共享给某个Team的记录,然后取消共享
    intiSuccess=0;intiFaile=0;varadminService=CrmServiceClientCommon.GetService();//创建QueryExpression对象QueryExpressionquery=newQueryExpression("opportunity");......
  • Solution - Atcoder AGC052B Tree Edges XOR
    令\(w_{(u,v)}\)为边\((u,v)\)的边权。考虑到对于一条边进行操作影响的是有公共点的边,于是一个想法是把边权转到点权,用点权来表示边权。于是考虑对于每个点构造\(w_u\)使得\(w_{(u,v)}=w_u\oplusw_v\)。因为这是一颗树,所以一定存在合法的构造。其实到了这里,这种......
  • Atcoder ABC296 F
    AtcoderABC296FF-SimultaneousSwap链接:F-SimultaneousSwap(atcoder.jp)简要题意:问题陈述给你两个\(N\)数字序列:\(A=(A_1,A_2,\ldots,A_N)\)和\(B=(B_1,B_2,\ldots,B_N)\)。高桥可以重复下面的操作任意多次(可能为零)。在\(1\)和\(N\)之间选择三......