agc001 vp记录

AGC质量是真的高啊


  • [AGC001A] BBQ Easy
    史努克在参加一个BBQ派对, 他要准备N组食物, 他有2N的食材, 需要两两组成一个食物, 食物的价值是两食材中较小的那个。 问最大总价值是多少

 
 
签到题。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=400;
int n,sum[N],ans;
signed main(){
	n=rd()*2;
	for(int i=1;i<=n;i++)sum[i]=rd();
	sort(sum+1,sum+1+n);
	for(int i=1;i<=n;i+=2)ans+=sum[i];
	printf("%d\n",ans);
	return 0;
}

高桥くん有一个边长为N的三枚镜子构成的正三角形, 顶点为a, b, c。他有一个超级步枪,放在AB段的P点上,使得AP=X。并沿着平行于BC的方向发射一道光。
光以直线传播,以镜子的形式反射,但是有一个特殊的地方:它会被自己的轨迹反射,当光回到步枪的时候,光被吸收。
下面的图显示了当n=5,x=2时的光轨迹。
avatar
无论光线轨迹和n和x如何, 求出光线的总长度。

 
 
问题规模逐步缩小,于是可以考虑递归求解,手推一下规律发现每次对答案的贡献是 2×(xxmody),其中 x 和 y 是长边和短边的长度。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
int ans,n,m;
void dfs(int x,int y){
	if(!y)return ans-=x,void(0);
	ans+=2*(x-x%y);
	dfs(y,x%y);
	return ;
}
signed main(){
	n=ans=rd(),n-=(m=rd());
	dfs(n,m);
	printf("%lld\n",ans);
	return 0;
}

你需要删除一些点,使树的直径小于等于K,当且仅当删除某点不会对树的联通性产生影响时才可以删除。问至少删除多少点才可以满足要求。
 
 
简单树形DP,随便推一下就行。这题为啥能评紫

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=2010;
int n,K,f[N][N],g[N][N],dep[N],siz[N],ans=INT_MAX;
int head[N],to[N*2],fro[N*2],tail;
inline void adlin(int x,int y){
	to[++tail]=y,fro[tail]=head[x],head[x]=tail;
	return ;
}
void dfs(int u,int fa){
	siz[u]=1;
	f[u][0]=0;
	for(int k=head[u];k;k=fro[k]){
		int x=to[k];
		if(x==fa)continue;
		dfs(x,u),siz[u]+=siz[x];
		dep[u]=max(dep[u],dep[x]+1);
		for(int i=0;i<=dep[u];i++)g[u][i]=INT_MAX;
		for(int i=dep[u];i>=0;i--){
			for(int j=0;j<=dep[x]&&i+j<=K;j++){
				g[u][max(i,j)]=min(g[u][max(i,j)],f[u][i]+f[x][j]);
			}
		}
		for(int i=0;i<=dep[u];i++)f[u][i]=g[u][i];
	}
	for(int i=dep[u];i>=1;i--)f[u][i]=f[u][i-1];
	f[u][1]=min(f[u][1],siz[u]-1),f[u][0]=siz[u];
	if(siz[u]==1)dep[u]=1;
	for(int i=0;i<=dep[u];i++)ans=min(ans,n-siz[u]+f[u][i]);
//	cout<<u<<":"<<dep[u]<<":";
//	for(int i=0;i<=dep[u];i++)cout<<f[u][i]<<" ";
//	cout<<"\n";
	return ;
}
signed main(){
	n=rd(),K=rd();
	for(int i=1;i<n;i++){
		int x=rd(),y=rd();
		adlin(x,y),adlin(y,x);
	}
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j]=INT_MAX;
	dfs(1,0);
	printf("%lld\n",ans);
	return 0;
}

  • [AGC001D] Arrays and Palindrome
    这题就不搬题面了。谢谢翻译的人我打死没看懂你翻译的是什么
    简单的使得回文串移位的构造题,代码更清晰。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=100010;
int n,m,a[N],b[N],t;
signed main(){
	n=rd(),m=rd();
	for(int i=1;i<=m;i++){
		a[i]=rd();
		if(a[i]&1)b[++t]=i;
	}
	if(t>2){
		printf("Impossible\n");
		return 0;
	}
	if(t>=1)swap(a[1],a[b[1]]);
	if(t>=2)swap(a[m],a[b[2]]);
	for(int i=1;i<=m;i++)printf("%d ",a[i]);
	printf("\n");
	b[1]=a[1]+1;
	for(int i=2;i<=m;i++)b[i]=(i==m)?a[i]-1:a[i];
	if(m==1){
		if(a[1]==1)printf("1\n1");
		else printf("2\n%d %d\n",a[1]-1,1);
		return 0;
	}
	if(a[m]==1)m--;
	printf("%d\n",m);
	for(int i=1;i<=m;i++)printf("%d ",b[i]);
	return 0;
}

有 n 个数对 (Ai; Bi),求出

i=1nj=i+1n(ai+bi+aj+bjai+aj)

答案对1e9+7取模

 
 
高妙组合题(然而被机房大佬说是典中典)。
这个式子不太能做,我们要将它拆分为之和 i 或 j 有关的部分。
n 1e5 不太能做,然而 a b 值域只有2000,于是考虑组合意义。
上式代表从(0,0)走到(ai+aj,bi+bj),如果将线路平移到从(ai,bi)(aj,bj)仍然成立。
现在之和i,j单独相关了。
于是我们将所有(ai,bi)加1,左下向右上做一遍DP,统计每个(ai,bi)处的答案。
减去自己到自己的部分,即(2×(ai+bi)2×ai)
最终答案除二。

实际也是有强推式子的做法,具体见luogu题解。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=5010,M=100000,K=2050,mod=1000000007;
int n,a[200010],b[200010],f[N][N];
int fps[M],inv[M],ans;
inline int pw(int x,int y){
	int ansn=1;
	while(y){
		if(y&1)ansn=ansn*x%mod;
		x=x*x%mod,y/=2;
	}
	return ansn;
}
inline int C(int x,int y){return fps[x]*inv[y]%mod*inv[x-y]%mod;}
signed main(){
	fps[0]=inv[0]=1;
	for(int i=1;i<M;i++)fps[i]=fps[i-1]*i%mod;
	inv[M-1]=pw(fps[M-1],mod-2);
	for(int i=M-2;i>=1;i--)inv[i]=inv[i+1]*(i+1)%mod;
	n=rd();
	for(int i=1;i<=n;i++)a[i]=rd(),b[i]=rd();
	for(int i=1;i<=n;i++)f[-a[i]+K][-b[i]+K]++;
	for(int i=0;i<=K*2;i++){
		for(int j=0;j<=K*2;j++){
			f[i+1][j]+=f[i][j],f[i+1][j]%=mod;
			f[i][j+1]+=f[i][j],f[i][j+1]%=mod;
		}
	}
	for(int i=1;i<=n;i++)ans+=f[a[i]+K][b[i]+K],ans%=mod;
	for(int i=1;i<=n;i++)ans-=C(a[i]*2+b[i]*2,a[i]*2),ans=(ans%mod+mod)%mod;
	printf("%lld\n",ans*inv[2]%mod);
	return 0;
}

  • [AGC001F] Wide Swap
    给出一个元素集合为{1,2,,N} (1N500,000)的排列P,当有i,j (1i<jN)满足jiK (1KN1)|PiPj|==1时,可以交换PiPj

求:可能排列中字典序最小的排列

 
 
人类智慧题。
考虑第一个条件不太好做,然而第二个条件有非常优良的限制,于是人类智慧:令 Qpi=i,能否交换相邻两个即为相邻数差是否大于等于 K 。
考虑冒泡排序,时间O(n2),不优,如何优化?
使用归并排序,先处理一个左边的后缀最小值,右边的数能比左边的先归并当且仅当右边的数加 K 小于等于左边数的后缀最小值。
关键还是要从题目条件入手。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=500010;
int n,K,sum[N],p[N],mi[N];
void merge(int l,int r){
	if(l==r)return ;
	int mid=(l+r)/2;
	merge(l,mid),merge(mid+1,r);
	for(int i=mid,x=INT_MAX;i>=l;i--)x=mi[i]=min(p[i],x);
	int ll=l,rr=mid+1,t=l;
	while(ll<=mid&&rr<=r){
		if(p[ll]>p[rr]&&mi[ll]>=p[rr]+K)sum[t++]=p[rr++];
		else sum[t++]=p[ll++];
	}
	while(ll<=mid)sum[t++]=p[ll++];
	while(rr<=r)sum[t++]=p[rr++];
	for(int i=l;i<=r;i++)p[i]=sum[i];
	return ;
}
signed main(){
	n=rd(),K=rd();
	for(int i=1;i<=n;i++)p[rd()]=i;
	merge(1,n);
	for(int i=1;i<=n;i++)sum[p[i]]=i;
	for(int i=1;i<=n;i++)printf("%d\n",sum[i]);
	return 0;
}
posted @   flywatre  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示