首页 > 其他分享 >Atcoder Beginner Contest 315 D~G

Atcoder Beginner Contest 315 D~G

时间:2023-08-20 23:12:25浏览次数:45  
标签:Atcoder le frac Beginner 10 int 315 long 5050

D

题意:给定一个 \(n\times m\) 的字符矩形,重复执行以下操作直到删除字符数为0:

  1. 对于每一行,若有且仅有一种字符存在,且个数大于1,将这些字符标记
  2. 对于每一列,若有且仅有一种字符存在,且个数大于1,将这些字符标记
  3. 删除所有标记的字符

求最后还能剩下多少字符。

注意到每一行每一列最多被删一次,我们可以用队列模拟这个操作,每次更新时间复杂度是 \(O(n+m)\),并将被删数标记。

时间复杂度 \(O((n+m)^2)\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 505050
char a[5050][5050];
int h[5050][300],r[5050][300],vis[5050][5050],s[N][2],n,m,sur[N][2];
struct node{
	int id,opt;
};
queue<node>q;
signed main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			h[i][a[i][j]-'a']++,r[j][a[i][j]-'a']++;	
			s[i][0]++,s[j][1]++;
		}
	}
	for(int i=1;i<=n;i++)for(int j=0;j<26;j++)sur[i][0]+=(h[i][j]>0);
	for(int i=1;i<=m;i++)for(int j=0;j<26;j++)sur[i][1]+=(r[i][j]>0);
	for(int i=1;i<=n;i++)if(sur[i][0]==1&&s[i][0]!=1){
		q.push((node){i,0});
	}
	for(int i=1;i<=m;i++)if(sur[i][1]==1&&s[i][1]!=1){
		q.push((node){i,1});
	}
	while(!q.empty()){
		node u=q.front();q.pop();
		if(u.opt==0){
			for(int i=1;i<=m;i++){
				if(vis[u.id][i]==0){
					vis[u.id][i]=1;r[i][a[u.id][i]-'a']--;s[i][1]--;
					if(r[i][a[u.id][i]-'a']==0){
						sur[i][1]--;if(sur[i][1]==1&&s[i][1]!=1)q.push((node){i,1});
					}
				}
			}
		}
		else {
			for(int i=1;i<=n;i++){
				if(!vis[i][u.id]){
					vis[i][u.id]=1;h[i][a[i][u.id]-'a']--;s[i][0]--;
					if(h[i][a[i][u.id]-'a']==0){
						sur[i][0]--;
						if(sur[i][0]==1&&s[i][0]!=1)q.push((node){i,0});
					}
				}
			}
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			ans+=(vis[i][j]==0);
		}
	}
	cout<<ans<<"\n";
}

E

题意:给定若干本书,在读第 \(i\) 本书之前,需要读 \(p_i\) 本书,分别是 \(c_{i,1}\sim c_{i,p_i}\)

求一个读书顺序,使得读的书最少且满足读了这些书之后就可以读第一本书。数据保证有解。

首先,我们建立两张有向图,第一张图的边形如 \((i,j)\),意为读第 \(i\) 本书必须要读第 \(j\) 本书。第二张图是第一张图的反图。

然后我们在第一张图从点1开始跑,标记到达的所有点,这些书是必读书,其他书没有任何关系。

接下来这个顺序,便可以在第二张图里只对被标记的点进行Topsort即可。

F

赛上一直以为是优先队列模拟,最后3min意识到是DP,却是没了时间。

题意:给定 \(n\) 个平面上的点 \((x_i,y_i)\),你需要从1号节点按顺序走到 \(n\) 号节点,从点 \(i\) 走到点 \(i+1\) 的代价为二者的欧几里得距离。

现在你可以选择跳过其中一部分点,不可以跳过点1和点 \(n\),假设你跳过了 \(c\) 个点,就需要付出 \(2^{c-1}\) 的额外代价(\(c=0\) 时候需要付出0代价)

求你最终需要付出的代价最小值。你的答案不可以和标准答案误差超过 \(10^{-5}\)

范围:\(2\le n\le 10^4,0\le x_i,y_i\le 10^4\),不存在两个重合的点。

首先估计答案上界,不跳过点,其代价最多为 \(n\sqrt {2\times 10^8}\le 10^8\sqrt 2< 2^{30}\)

所以说,\(c\) 是不可能超过 \(29\) 的。这时候可以考虑直接枚举 \(c\) 计算答案。

怎么算?最优化问题,可以选择跳过,问题可划分可拼凑,明显的动态规划。

设 \(f_{i,j}\) 为前 \(i\) 个点里跳过 \(j\) 个点,在第 \(i\) 个点落脚所付出的最小代价。

显然有 \(f_{i,j}=\min_{j\ge (i-k-1)}f_{k,j-(i-k-1)}+dis(k,i)\)

然后枚举答案,\(\min f_{n,i}+2^{i-1}\)。复杂度 \(O(nc^2)\)

当附加代价单一可以通过某参数单独计算时,可先不考虑附加代价,最后处理即可

signed main(){
	cin>>n;
	db ans=1e18;
	for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
	f[1][0]=0;
	for(int j=0;j<=30ll;j++){
		for(int i=2;i<=n;i++){
			f[i][j]=1e18;
			for(int k=1;k<i;++k)if(i-k-1<=j)f[i][j]=min(f[i][j],f[k][j-(i-k-1)]+dis(i,k));	
		}
	}
	for(int c=0;c<=30;++c){
		db res;
		if(c==0)res=0;
		else res=(1<<(c-1));db mn=1e18;
		for(int i=0;i<=min(n,c);i++)mn=min(mn,f[n][i]);
		res+=mn;
		ans=min(ans,res);
	}
	printf("%.15f",ans);
}

G

题意:给定 \(N,A,B,C,X\),求满足以下条件的 \((i,j,k)\) 个数:

\[Ai+Bj+Ck=X,1\le i,j,k\le N \]

\(1\le N\le 10^6,1\le A,B,C\le 10^9,1\le X\le 3\times 10^{15}\)

在这个问题中,注意到下界是1,不方便处理,可令 \(X'=X-A-B-C,N'=N-1\),将下界化为0

首先,注意到 \(N\) 比较小,可以进行枚举 \(i\),那么式子就化为 \(Bx+Cy=X'\),其中 \(X'=X-Ai\)。

设 \(d=\gcd(B,C)\),若 \(d\) 不整除 \(X'\),则直接 continue

我们设 \(b=\frac{B}{d},c=\frac{C}{d}\),另用exgcd求一组特解 \(Bx_0+Cy_0=d\),并将 \(x_0\) 化为最小非负整数解。(防爆long long)

然后,我们对于 \(Bx+Cy=X'\),先令 \(x_1=x_0·\frac{X'}{d}\bmod c\)(有细节,需提前模),同时求出另一个对应的 \(y_1\)。

此时注意到合法的系数必定是在一段区间之内,设端点为 \(l,r\)。

注意以下简称系数是指周期数,也即解的个数。
此时必定有 \(x_1\) 是最小解了,那么它的系数的 \(l\) 应该由 \(y_1\) 来限制,也即 \(l=\lceil\frac{(y_1-N)}{b}\rceil\)。

这是要找出令 \(y'_1\le N\) 的最小系数。当然有可能 \(y_1\le N\),此时应当令 \(l=0\)

综上,\(l=\max(0,\lceil\frac{(y_1-N)}{b}\rceil)\)

然后考虑求最大解。有两种情况:

  • 一是由 \(y\) 来决定,它取最小值时,\(x\) 取得最大系数,是 \(\lfloor\frac{y_1}{b}\rfloor\)(之所以下取整是要留一个最小非负解)。
  • 二是由 \(x\) 来决定,它最大可以取到 \(\lfloor\frac{N-x_1}{c}\rfloor\)。

所以 \(r=\min(\lfloor\frac{N-x_1}{c}\rfloor,\lfloor\frac{y_1}{b}\rfloor)\)

当然,若 \(x_1>N\),亦或者 \(y_1<0\),这都是非法的,直接令 \(r=-1\) 即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int get(int a,int b,int c,int &x,int &y){//ax+by=c 
	int d=exgcd(a,b,x,y);x*=c/d,y*=c/d;
	return d;
}
int N,A,B,C,X;
signed main(){
	ios::sync_with_stdio(false);
	cin>>N>>A>>B>>C>>X;
	N--,X-=A+B+C; 
	if(X<0){
		puts("0");return 0;
	}
	int x0,y0;
	int d=exgcd(B,C,x0,y0),b=B/d,c=C/d,ans=0;//k0=b,k1=c
	x0%=c;y0=(d-B*x0)/C;
	for(int i=0;i<=N;i++){
		int x=X-i*A;
		if(x%d!=0)continue;
		if(x<0)break;
		int l,r,x1=x/d%c*x0,y1;x1=(x1%c+c)%c,y1=(x-x1*B)/C;
		l=max(0ll,(y1-N+b-1ll)/b);
		if(x1>N||y1<0)r=-1ll;
		else r=min((N-x1)/c,y1/b);
		if(l<=r)ans+=r-l+1;
	}
	cout<<ans;
}

标签:Atcoder,le,frac,Beginner,10,int,315,long,5050
From: https://www.cnblogs.com/oierpyt/p/17644846.html

相关文章

  • AtCoder 题目集2
    AtCoder题目集2终于迈入了一个新的阶段,接下来希望质量能高一点吧。现在我主要刷的是1600左右的题,毕竟实力太拉,只能按照”分上200“的策略。(我觉得类型标个“思维”貌似没啥意义,毕竟AT几乎全是思维啊...)编号(NO.)题目难度类型1ABC201E1694,medium思维,XOR......
  • Atcoder Beginner Contest 315 解题报告
    AtcoderBeginnerContest315ContestlinkHintsD尝试优化暴力。A-tcdr没啥好说的,模拟。代码实现voidSolve(){ while(charch=getchar()) { if(!isalpha(ch))return; if(ch!='a'&&ch!='e'&&ch!='i'&&ch!='o......
  • AtCoder Beginner Contest 315
    A模拟,代码。B模拟,代码。C我们发现美味度最高的食物必选,排序后枚举即可。代码。D模拟。代码。EDFS。代码。F我们发现\(2^C\)增长很快,因此不选的数量最多只有\(\log\)次,直接DP即可。代码。G我们枚举\(i\),那么也就是求出\(Bj+Ck=X-Ai(1\lej\leN,1\lek\l......
  • AtCoder 题目集1
    AtCoder题目集1这是一个AT个人刷题总结的开始,感觉确实应该做一做这种总结,如果只是不断的刷题,感觉貌似也没有什么意思,还不如时常适当的回望一下过去的好题。希望能一直做下去吧。update(22.12.14):AT赛后总结归为另外一栏,此处为过去AT题目的记录。总结了一些比较有趣或者有思......
  • ABC315
    T1:tcdr模拟代码实现#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;cin>>s;erase_if(s,[](charc){returnranges::count("aeiou",c);});cout<<s<<'\n';......
  • IT3158 业务决策建模
    IT3158BusinessDecisionModellingAssignment1:LinearProgramming,SensitivityAnalysis,andIntegerLinearProgramming-usingMicrosoftExcelSolverThisassignmentisworth30%ofyourfinalmark(subjecttothehurdlesdescribedintheFIT3158UnitGu......
  • AtCoder Beginner Contest 288 - C Don't be cycle 删除图中最少的边使得图中无环
    C-Don'tbecycle题意给定一个n个顶点,m条边的无向图,你需要删除图中的一些边使得图中不存在环问你需要删除的最少边数?思路考虑连通块的生成树一个由n个顶点组成的连通块最多只能有n-1条边,不然就会成环。那么对于本题,我们只需要找到每个连通块的顶点数,那么每个连......
  • Atcoder_[abc284E]Count Simple Paths题解
    题目链接这题就是很简单的图上深搜,我觉得放在E题太水了,代码里有详细注释。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvector<int>v[200010];//邻接表intans;//答案boolvis[200010];//vis[i]记录i号点有没有被访问过voiddfs(intx)......
  • AtCoder Beginner Contest 311 - D(思维题)
    目录D-GridIceFloorABC简单题D思维题D-GridIceFloor题意给定一个\(n\timesm\)的矩阵,矩阵每个位置上的字符要么是'.'要么是'#',保证矩阵的最外围一圈都是'#'。玩家初始位于位置(2,2)。玩家可以进行移动,但是移动有条件:玩家首先选定一个移动方向,之后在这个方......
  • AtCoder-ABC-267 C - Index × A(Continuous ver
    C-Index×A(Continuousver.)题目大意:给定n个数(\(a_1,a_2...a_n\)),从中选连续m个数,这m个数的和为:\(\sum_{i=1}^mi*b_i\)求最大的和为多少。\(1<=m<=n<=2*10^5\)\(-2*10^5<=a_i<=2*10^5\)解题思路首先m个数为一组,那么最多有n-m+1组,这个数量是可以被遍历的,但是......