首页 > 其他分享 >AtCoder Beginner Contest 363

AtCoder Beginner Contest 363

时间:2024-07-28 15:29:06浏览次数:16  
标签:AtCoder pq Beginner int tt long tp 363 回文

比赛地址添加链接描述

A - Piling Up

算法: 模拟

题目大意

在 AtCoder 竞赛平台中,用户的等级通过正整数分数表示,并根据分数显示相应数量的 ^ 符号。分数与 ^ 符号显示的规则如下:

当分数在 1 到 99(包括 99)之间时,显示一个 ^。
当分数在 100 到 199(包括 199)之间时,显示两个 ^。
当分数在 200 到 299(包括 299)之间时,显示三个 ^。
当分数在 300 到 399(包括 399)之间时,显示四个 ^。
高桥当前的分数是 R,题目保证 R 是一个介于 1 到 299 之间的整数。

任务是求出高桥需要增加的最小分数,使得他的 ^ 符号显示数量增加一个。

算法思路

重点就是读懂题目,基本没什么思路,只需要模拟即可。

代码

#include<stdio.h>
#define ll long long
const int N = 3e5+7;

void slove() {
	int n;
	cin>>n;
	if(n<=99) cout<<100-n;
	else if(n<=199) cout<<200-n;
	else if(n<=299) coiut<<300-n;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	slove();
	return 0;
}

B - Japanese Cursed Doll

算法

题目大意

算法思路

代码

B - Japanese Cursed Doll

算法:贪心+模拟

题目大意

有 N 个人,每个人当前的头发长度为 Li(长度单位为厘米)。每个人的头发每天都会均匀增长 1 厘米。

给定两个整数 T 和 P,分别代表特定的头发长度阈值和人数阈值。

任务是找出从某天开始,头发长度至少为 T 厘米的人数首次达到或超过 P 人的那一天的天数。如果一开始至少有 P 人的头发长度已经达到或超过 T 厘米,则输出的天数应该是 0。

算法思路

因为数据并不是很大,只需要先排序,然后在进行模拟即可。

代码

#include<bits/stdc++.h>
#define ll long long
const int N = 1e5+7;
using namespace std;
int a[N];
void slove() {
	int n,t,p;
	cin>>n>>t>>p;
	for(int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+n+1,greater<int>());
	cout<<max(0,t-a[p]);
	return;
}
int main(){
	slove();
	return 0;
}

C - Avoid K Palindrome 2

算法:dfs+字符串操作+模拟

题目大意

给定一个由小写英文字母组成的字符串 S,其长度为 N。

要求计算通过置换(排列)字符串 S 中的字符后,所得到的字符串中不包含任何长度为 K 的回文子串的排列方式有多少种。

一个字符串被认为是长度为 K 的回文,如果它正读和反读都一样,并且这个回文子串的长度不超过 N-K+1。
如果通过置换字符能够得到不包含长度为 K 的回文子串的字符串,这样的置换方式算作一个有效结果。
任务是计算所有可能的置换中,满足条件的有效置换有多少种

算法思路

因为N的数据很小,那么我们可以对S进行全排列,然后对全排列以后的字符串进行判断,看是否存在长度为K的回文子串。

代码

#include<bits/stdc++.h>
#define ll long long
const int N = 1e5+7;
using namespace std;
map<string,int> mp;
int tp[15];
string s;
int n,k;
ll ans = 0;
bool check(string ts) {
	if(mp[ts]==1) return true;
	mp[ts] = 1;
	for(int i=0;i<ts.size()-k/2;++i) {
		int flag = 0;
		for(int j=0;j<k/2;j++) {
			if(ts[i+j]!=ts[i+k-j-1]) flag = 1;
		}
		if(flag == 0) return true;
	}
	return false;
}
void dfs(int x,string ts) {
	if(x==n) {
//		cout<<ts; 
		if(!check(ts)) ans++;
		return;	
	}
	for(int i=0;i<s.size();++i) {
		if(tp[i]==0) {
			tp[i]=1;
			dfs(x+1,ts+s.substr(i,1));
			tp[i]=0;
		}
	}
	return;
}
void slove() {
	cin>>n>>k;
	cin>>s;
	dfs(0,"");
	cout<<ans;
	return;
}
int main(){
	slove();
	return 0;
}

D - Palindromic Number

算法:贪心+模拟

题目大意

定义了一个特殊的数,称为回文数,它的十进制表示法(不包含前导零)正读和反读是一样的。
给出一些例子,如 363、12344321 和 0 都是回文数。
任务是求第 N 小的回文数。这意味着你需要找到一个数,它是所有回文数中第 N 个按数值从小到大排列的数。

算法思路

这题的思路比较巧,题目要求我们找到第N个回文数,因为第N个回文串本身数据比较大,超出了long long的范围,肯定无法通过常规方法进行输出,但我们可以通过一位一位打印输出。
例如46,我们可以知道长度为1的数字有10个(0,1,2,3,4,5,6,7,8,9),长度为2的数字有9个(11,22,33,44,55,66,77,88,99),又因为长度为3的回文数必须保证头尾相同,那么头尾为1的回文数有(101,111,121,131,141,151,161,171,181,191),从1-9都会有10个,所以我们能推出头尾是3,然后又是10个里面的第几个,就可以推出6,然后打印出来即可。
重点就是理解代码。

代码

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
const int N = 1e5+7;
const ull M = 1e18;
using namespace std;
//t存放的对应位数有多少回文数
ull t[107] = {0,10,9};
//tt存放的是包含前导0情况的回文数个数
ull tt[107] = {0,10,10};
//tans存放的是前缀和
ull tans[107] = {0,10,19};
ull ans = 19;
void slove() {
//	for(int i=1;i<=len;++i) cout<<t[i]<<endl;
//	cout<<len;

	ull n;
	cin>>n;
	ull i;
	//i确定所求的数是几位数
	for(i=1; i<=50; ++i) {
		if(n<=tans[i]) break;
	}
//	cout<<i;
	vector<int> ve;
	ull tn = n - tans[i-1];
//	cout<<tn<<endl;
	//一位一位处理
	for(ull ii=1; ii<=int(ceil(1.0*i/2)); ++ii) {
		//处理第几位数
		int tsz = i-(ii-1)*2;
		if(tsz == 1 || tsz == 2) {
			ve.push_back(tn-1);
		} else {
			if(ii==1) {
				if(tn%tt[tsz-2]==0) {
					ve.push_back(tn/tt[tsz-2]);
				} else ve.push_back(tn/tt[tsz-2]+1);
			} else {
				if(tn%tt[tsz-2]==0) {
					ve.push_back(tn/tt[tsz-2]-1);
				} else ve.push_back(tn/tt[tsz-2]);
			}
			if(tn%tt[tsz-2]==0) tn = tt[tsz-2];
			else tn %= tt[tsz-2];
		}
	}
	for(int ii=0; ii<ve.size(); ++ii) {
		cout<<ve[ii];
	}
	for(int ii=i-ve.size()-1; ii>=0; --ii) {
		cout<<ve[ii];
	}
	cout<<endl;
	return;

}
int main() {
	ull len = 3;
	while(1) {
		t[len] = 9*tt[len-2];
		tt[len] = 10*tt[len-2];
		ans += t[len];
		if(ans>=M) break;
		len++;
	}
	for(int i=3; i<=len; ++i) tans[i]+=t[i]+tans[i-1];
	slove();
	return 0;
}

E - Sinking Land

算法:BFS + 优先队列

题目大意

有一个小岛,其面积为 H 行乘以 W 列,即总的格子数为 H×W。小岛四周被海水包围。

小岛被划分为 H 行 W 列的正方形小块,每一块的海拔高度由二维数组 A[i][j] 给出,其中 i 是行号,j 是列号。

每年海平面上升 1 单位高度。根据以下规则,一些小块会逐渐沉入海中:

垂直或水平临海的小块,或者海拔高度不大于当前海平面高度的小块,将沉入海中。
当一个小块沉入海中时,与其垂直或水平相邻的、海拔高度不大于海平面的小块也会沉入海中。这个过程会连续发生,直到没有新的小块沉入海中。
任务是对每个年份 i(i=1,2,…,Y),求出经过 i 年后,岛上仍高于海平面的小块的总数。

算法思路

这题比较简单,其实就是海水蔓延的过程,通过BFS进行模拟即可,只不过需要通过priority_queue存储对应的数据即可。

代码

#include<bits/stdc++.h>
#define ll long long
const int N = 1e5+7;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
using namespace std;
struct Node {
	int x,y;
	int ans;
	bool operator<(const Node& b) const {
		return ans>b.ans;
	}
};
int h,w,yr;
int a[N];
int ta[1007][1007];
int tp[1007][1007];
priority_queue<Node> pq;
int ans;
void bfs(int nowyr) {
	if(nowyr>yr) return;
	while(!pq.empty() && nowyr>=pq.top().ans) {
		--ans;
		int x = pq.top().x;
		int y = pq.top().y;
		pq.pop();
		for(int i=0; i<4; ++i) {
			int tx = x + dx[i];
			int ty = y + dy[i];
			if(tx>=1 && tx<=h && ty>=1 && ty<=w && tp[tx][ty]==0) {
				tp[tx][ty] = 1;
				pq.push(Node {tx,ty,ta[tx][ty]});
			}
		}
	}
	a[nowyr] = ans;
	bfs(nowyr+1);
}
void slove() {
	cin>>h>>w>>yr;
	for(int i=1; i<=h; ++i)
		for(int j=1; j<=w; ++j)
			cin>>ta[i][j];
	ans = h * w;
	for(int i=1; i<=h; ++i) {
		if(w!=1) {
			tp[i][1] = 1;
			tp[i][w] = 1;
			pq.push(Node {i,1,ta[i][1]});
			pq.push(Node {i,w,ta[i][w]});
		} else {
			tp[i][1] = 1;
			pq.push(Node {i,1,ta[i][1]});
		}
	}
	for(int i=2; i<=w-1; ++i) {
		if(h!=1) {
			tp[1][i] = 1;
			tp[h][i] = 1;
			pq.push(Node {1,i,ta[1][i]});
			pq.push(Node {h,i,ta[h][i]});
		} else {
			tp[1][i] = 1;
			pq.push(Node {1,i,ta[1][i]});
		}

	}
	bfs(1);
	for(int i=1; i<=yr; ++i) cout<<a[i]<<endl;
	return;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	slove();
	return 0;
}

标签:AtCoder,pq,Beginner,int,tt,long,tp,363,回文
From: https://blog.csdn.net/congyuyoudao/article/details/140750924

相关文章

  • AtCoder Beginner Contest 364 补题记录(A~F)
    VP五十八分钟苏童流体。好耶A#defineGLIBCXX_DEBUG#include<iostream>#include<cstring>#include<cstdio>#defineintlonglongconstintN=500100;std::strings[N];signedmain(){intn,cnt=1;scanf("%lld",&n);f......
  • AtCoder Beginner Contest 364
    A-GluttonTakahashi(abc364A)题目大意给定\(n\)个字符串,问是否有两个相邻的sweet。解题思路遍历判断当前字符串与上一个字符串是否都为sweet即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_......
  • AtCoder Beginner Contest 364 复盘
    AtCoderBeginnerContest364当你发现你的做法假了时,再看看题目的时限和空限,你就有可能发现,你的做法真了。本场口胡出了\(5\)题的正解,但是只写出了\(3\)题。弱弱又智智。A-GluttonTakahashi&B-GridWalk&C-MinimumGlutton签到D-K-thNearest算口胡出半......
  • AtCoder Beginner Contest 362
    题目链接:AtCoderBeginnerContest362A.BuyaPentag:签到B.RightTriangletag:模拟C.RightTriangletag:贪心Description:给定\(n\)对整数\(l_i,r_i\);求一个整数序列,满足\(l_i<=x_i<=r_i\),且\(\sum_{i}^{n}x_i=0\);如果没有则输出\(-1\)。Solution:先判断是否有解,令......
  • AtCoder Beginner Contest 363
    上周去玩了(逃A-PilingUp(abc363A)题目大意给定分数,问晋级还差多少分。分别到\(100,200,300\)分能晋级。解题思路找到第一个大于当前分数的,其差即为答案。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){io......
  • ABC363
    Alink判断即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intr;signedmain(){ cin>>r; if(r<100)cout<<100-r; elseif(r<200)cout<<200-r; elseif(r<300)cout<<300-r; return0; }......
  • [ABC363G] Dynamic Scheduling 与 P4511 [CTSC2015] 日程管理
    思路:对于插入操作,设插入\(\{t,p\}\):若当前\(1\simt\)有空位,那么就放进去。否则,\(1\simt\)是被塞满了的:首先容易想到的是找到\(1\simt\)中贡献最小的那个工作,若贡献比\(p\)还小,可以与之替换掉。但是假了,考虑这样一种情况:在\(1\simt\)外有一个更小的......
  • AtCoder Beginner Contest 360 题解(C-E)
    C-MoveIt题目链接:C-MoveIt题目大意:有\(N\)个盒子和\(N\)个物品编号为\(1-N\),物品\(i\)在盒子\(A_i\)中,重量为\(W_i\),你可以进行一种操作将盒子中的一件物品移动到其他任意盒子中,代价为\(W_i\),求使得所有盒子中只存在一件物品的最小操作代价。题解:贪心,可以发现......
  • AT_abc363_e [ABC363E] Sinking Land Solution
    题目大意:有一座矩形岛屿,被分为\(H\timesW\)的网格,四周与海水接触,给定时间\(Y\)年,最初海平面位于高度\(0\\text{m}\),每年海水上升\(1\\text{m}\),请求出每年未被海水淹没的格子数(高度小于等于海水高度即为淹没)。显然有点类似于广搜的想法,用一个队列存储与海水接触的方......
  • [atcoder utpc2023_p] Priority Queue 3
    PriorityQueue3题意:有一个小根堆和\(1\)~\(n\)个数,以及一个操作序列,+表示\(push\),-表示\(pop\),\(pop\)有\(m\)次,问你有多少种插入顺序使得最后的pop集合与给出的的数字集合\(Y\)相同。首先有个浅显的发现:对于不在\(Y\)集合中的数,可选范围形如一个阶梯,换句话......