首页 > 其他分享 >2022-2023 ICPC East Central North America Regional Contest (ECNA 2022)

2022-2023 ICPC East Central North America Regional Contest (ECNA 2022)

时间:2024-02-02 19:11:43浏览次数:24  
标签:std cnt America Central int 2022 const include define

Preface

闲了两天没训练,今天又开始上班,结果唐得发昏后期也没题可写直接光速下班

只能说感觉老外的题目难度跨度都好大,easy确实简单,hard确实难,medium确实少


A. A-Mazing Puzzle

题目看起来很复杂,但仔细一想会发现有用的状态总数只有\(4n^2\)种

即我们可以暴力记录下两个机器人的坐标,然后记下其中一个机器人的方向,就可以唯一确定一个状态了(因为两个机器人的方向的相对差距是不变的,因此记一个就行)

然后转移的话就直接写一个类似Dijkstra的东西即可,要注意各种细节

#include<bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;
#define ft first
#define sd second

const int N = 55;
const int dir1[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
const int dir2[4][3] = {{0, 0, 0}, {1, 0, 0}, {0, 0, -1}, {1, -1, 0}};
const char pat[5] = "NESW";

int n, c, r, e;
int c1, r1, d1, c2, r2, d2;
bool wall[2][55][55];
int dis[52][52][52][52][2];
bool inD[52][52][52][52];

struct Node{
	int cc1, rr1, cc2, rr2;	
	pii d;
	bool operator<(const Node &b)const{return d > b.d;}
};


signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	memset(dis, 0x3f, sizeof(dis));
	char ch1, ch2;
	cin >> c >> r >> e;
	cin >> c1 >> r1 >> ch1 >> c2 >> r2 >> ch2;
	for (int i=0; i<4; ++i){
		if (ch1==pat[i]) d1=i;
		if (ch2==pat[i]) d2=i;
	}
	
	cin >> n;
	for (int i=1; i<=n; ++i){
		int c0, r0; cin >> c0 >> r0;
		wall[0][c0][r0]=true;
	}
	
	for (int i=1; i<=c; ++i) wall[0][i][0]=wall[0][i][r]=true;
	for (int i=1; i<=r; ++i) wall[1][0][i]=wall[1][c][i]=true;
	wall[0][e][0]=false;
	
	cin >> n;
	for (int i=1; i<=n; ++i){
		int c0, r0; cin >> c0 >> r0;
		wall[1][c0][r0]=true;
	}
	
	priority_queue<Node> que;
	que.push(Node{c1, r1, c2, r2, make_pair(0, 0)});
	dis[c1][r1][c2][r2][0]=0, dis[c1][r1][c2][r2][1]=0;
	
	while (!que.empty()){
		auto [cc1, rr1, cc2, rr2, pp] = que.top(); que.pop();
//		printf("cc1=%d rr1=%d cc2=%d rr2=%d pp(%d %d)\n", cc1, rr1, cc2, rr2, pp.ft, pp.sd);
		if (inD[cc1][rr1][cc2][rr2]) continue;
		inD[cc1][rr1][cc2][rr2]=true;
		
		for (int j=0; j<4; ++j){
			int bp=0;
			int nc1, nr1;
			auto [a1, b1, c1] = dir2[(j+d1)%4];
			if (wall[a1][cc1+b1][rr1+c1]) nc1=cc1, nr1=rr1, ++bp;
			else if (cc1==e && rr1==0) nc1=cc1, nr1=rr1;
			else nc1=cc1+dir1[(j+d1)%4][0], nr1=rr1+dir1[(j+d1)%4][1];
			
			int nc2, nr2;
			auto [a2, b2, c2] = dir2[(j+d2)%4];
			if (wall[a2][cc2+b2][rr2+c2]) nc2=cc2, nr2=rr2, ++bp;
			else if (cc2==e && rr2==0) nc2=cc2, nr2=rr2;
			else nc2=cc2+dir1[(j+d2)%4][0], nr2=rr2+dir1[(j+d2)%4][1];
			
			if (bp==2) continue;
			if (nc1==nc2 && nr1==nr2 && !(nc1==e && nr1==0)) continue;
			pii npp = make_pair(pp.ft+1, pp.sd+bp);
//			printf("nc1=%d nr1=%d nc2=%d nr2=%d, npp(%d %d)\n", nc1, nr1, nc2, nr2, npp.ft, npp.sd);
			
			if (npp < make_pair(dis[nc1][nr1][nc2][nr2][0], dis[nc1][nr1][nc2][nr2][1])){
				que.push(Node{nc1, nr1, nc2, nr2, npp});
				dis[nc1][nr1][nc2][nr2][0]=npp.ft;
				dis[nc1][nr1][nc2][nr2][1]=npp.sd;
//				if ((nc1==e && nr1==0) && (nc2==e && nr2==0)){
//					printf("FUCKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n");
//				}
			}
		}	
//			puts("");
	}
	cout << dis[e][0][e][0][0] << ' ' << dis[e][0][e][0][1] << '\n';
	
	return 0;
}	

B. A Musical Question

签到,直接暴力DP即可,二元组\((x,y)\)表示第一张唱片刻录长度为\(x\)的歌,第二张唱片刻录长度为\(y\)的歌的状态

#include<cstdio>
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=1005;
int n,m; bool vis[N][N];
int main()
{
	RI i; vector <pi> S; S.push_back(pi(0,0)); vis[0][0]=1;
	for (scanf("%d%d",&m,&n),i=1;i<=n;++i)
	{
		int w; scanf("%d",&w); vector <pi> NS;
		for (auto [x,y]:S)
		{
			if (x+w<=m&&!vis[x+w][y]) vis[x+w][y]=1,NS.push_back(pi(x+w,y));
			if (y+w<=m&&!vis[x][y+w]) vis[x][y+w]=1,NS.push_back(pi(x,y+w));
		}
		for (auto it:NS) S.push_back(it);
	}
	int ans1=0,ans2=0; for (auto [x,y]:S)
	if (x+y>ans1+ans2||(x+y==ans1+ans2&&abs(x-y)<abs(ans1-ans2))) ans1=x,ans2=y;
	return printf("%d %d",max(ans1,ans2),min(ans1,ans2)),0;
}

C. Cribbage On Steroids

首先pair的贡献很好算,然后顺子的话只要枚举顺子的起点和终点即可快速算贡献

至于15's的话可以直接大力DP,设\(f_{i,j}\)表示用前\(i\)种点数的牌组成价值和为\(j\)的牌面的方案数,转移很trivial

#include<bits/stdc++.h>
using namespace std;
#define int long long

int C[105][105];
int n, cnt[20];
int sum[20];
int f[20][20];

signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	C[0][0]=C[1][0]=C[1][1]=1;
	for (int i=2; i<105; ++i){
		C[i][0]=C[i][i]=1;
		for (int j=1; j<i; ++j)	C[i][j]=C[i-1][j]+C[i-1][j-1];
	}
//	for (int i=0; i<=100; ++i) printf("C[100][%d]=%lld\n", i, C[100][i]);
	cin >> n;
	for (int i=1; i<=n; ++i){
		char ch; cin >> ch;
		if ('T'==ch) ++cnt[10];
		else if ('J'==ch) ++cnt[11];
		else if ('Q'==ch) ++cnt[12];
		else if ('K'==ch) ++cnt[13];
		else if ('A'==ch) ++cnt[1];
		else ++cnt[ch-'0'];
	}
	int ans=0;
	for (int i=1; i<=13; ++i){
		sum[i] += sum[i-1]+i*cnt[i];
	}	
	for (int i=1; i<=13; ++i){
		if (cnt[i]>=2) ans += cnt[i]*(cnt[i]-1);
	}
//	printf("ans=%lld\n", ans);
	
	int lst=0, res=1;
	for (int i=1; i<=14; ++i){
		if (0==cnt[i]){
			if (i-lst-1>=3) ans += res*(i-lst-1);
			res=1; lst=i;
		}else res*=cnt[i];
	}
//	printf("ans=%lld\n", ans);
	cnt[10]+=cnt[11];
	cnt[10]+=cnt[12];
	cnt[10]+=cnt[13];
	
	f[0][0]=1;
	for (int i=1; i<=10; ++i){
		for (int j=0; j<=15; ++j){
			for (int k=0; k<i; ++k){
				for (int w=1; w<=cnt[i]; ++w){
					if (w*i>j) break;
					f[i][j]	+= f[k][j-w*i]*C[cnt[i]][w];
				}
			}
		}
	}	
	for (int i=1; i<=10; ++i) ans += f[i][15]*2;
	cout << ans << '\n';
	
	return 0;
}	

D. Determining Nucleotide Assortments

签到,注意不要搞错ATGC的顺序

#include<bits/stdc++.h>
using namespace std;

const int N = 5e4+5;
using pii = pair<int, int>;
#define ft first
#define sd second

int n, q;
int cnt[4][N];
char pat[5] = "ATGC";
char str[N];

signed main(){
	scanf("%s", str+1);
	n = strlen(str+1);
	for (int i=1; i<=n; ++i){
		for (int j=0; j<4; ++j){
			if (str[i]==pat[j]) ++cnt[j][i];	
		}
	}
	for (int i=1; i<=n; ++i){
		for (int j=0; j<4; ++j){
			cnt[j][i] += cnt[j][i-1];	
		}
	}
	scanf("%d", &q);
	while (q--){
		int l, r; scanf("%d%d", &l, &r);
		vector<pii> vec;
		for (int j=0; j<4; ++j) vec.push_back(make_pair(cnt[j][r]-cnt[j][l-1], j));
		sort(vec.begin(), vec.end(), [&](pii a, pii b){return a.ft!=b.ft ? a.ft>b.ft : a.sd<b.sd;});
		for (auto [a, b] : vec) putchar(pat[b]);
		puts("");
	}
	
	return 0;	
}

E. Hilbert's Hedge Maze

因为前面我太唐了没给徐神留出足够的时间,红豆泥私密马赛

这题徐神给我讲了做法我也没太懂,只能说笨比脑子是这样的,只能坐等徐神补题了


F. It's About Time

大力枚举+小推式子,对于徐神来说就是洒洒水

#include <bits/stdc++.h>

int main() {
    const long double pi = std::acos(-1.L);
    long double r, s, h;
    std::cin >> r >> s >> h;
    const long double tyear = 2.L * pi * r / (s * h);
    const long double cy = std::round(tyear);
    const long double ly = cy < tyear ? cy + 1.L : cy - 1.L;
    long double mindelta = 1e9;
    std::array<int, 3> ans;
    for(int n1 = 2; n1 < 1000; ++n1) {
        for(int n2 = n1 + n1; n2 < 1000; n2 += n1) {
            for(int n3 = n2 + n2; n3 <= 1000; n3 += n2) {
                const int l = n3 / n1 - n3 / n2 + n3 / n3;
                const int c = n3 - l;
                const long double aver = (l * ly + c * cy) / (long double)n3;
                if(std::abs(aver - tyear) < mindelta) {
                    mindelta = std::abs(aver - tyear);
                    ans = {n1, n2, n3};
                }
            } 
        }
    }
    std::cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << std::endl;
    return 0;
}

G. Pea Pattern

这种乍一看不知道有什么好做法,但是一看榜被过穿了的题,首先考虑大力出奇迹

直觉告诉我们这个序列做到后面很快就会产生重复,因此如果有解的话直接暴力模拟即可

#include<cstdio>
#include<iostream>
#include<set>
#include<string>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
string n,m;
int main()
{
	RI i; cin>>n>>m; set <string> ext;
	if (n.size()>100||m.size()>100) return puts("I'm bored."),0;
	for (int cnt=1;;++cnt)
	{
		if (n==m) return printf("%d",cnt),0;
		if (ext.count(n)) break; ext.insert(n);
		static int c[10]; memset(c,0,sizeof(c));
		for (i=0;i<n.size();++i) ++c[n[i]-'0'];
		string t=""; for (i=0;i<10;++i) if (c[i]) t+=to_string(c[i])+char('0'+i); n=t;
	}
	return puts("Does not appear"),0;
}

H. Picking Up Steam

好难的几何,大致有个思路但貌似细节很多不太好写


I. Road To Savings

祁神写的,我题目都没看

#include<bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;
const int INF = (int)1e8+5;
const int N = 205;

int n, m, src, dr;
int dis[N][N];
struct Edge{int a, b, w;};
vector<Edge> G;

signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n >> m >> src >> dr;
	for (int i=1; i<=n; ++i){
		for (int j=i+1; j<=n; ++j){
			dis[i][j] = dis[j][i] = INF;
		}
	}
	for (int i=1; i<=m; ++i){
		int a, b, w; cin >> a >> b >> w;
		dis[a][b] = dis[b][a] = w;
		G.push_back(Edge{a, b, w});
	}
	for (int k=1; k<=n; ++k){
		for (int i=1; i<=n; ++i){
			for (int j=1; j<=n; ++j){
				if (dis[i][k]+dis[k][j]<dis[i][j]) dis[j][i]=dis[i][j] = dis[i][k]+dis[k][j];
			}
		}
	}
	int dist = dis[src][dr];
	int ans=0;
//	
//	for (int i=1; i<=n; ++i){
//		for (int j=1; j<=n; ++j){
//			printf("%d ", dis[i][j]);
//		}puts("");
//	}
	
	
	for (auto [a, b, w] : G){
//		printf("(%d %d) %d %d\n", a, b, dis[src][a]+dis[b][dr], dis[src][b]+dis[a][dr]);
		if (dis[src][a]+dis[b][dr]+w > dist && dis[src][b]+dis[a][dr]+w > dist) ans += w;
	}
	cout << ans;
	return 0;
}	

J. Simple Solitaire

徐神写的,我题目都没看(怎么又是打牌啊)

#include <bits/stdc++.h>

bool shrink(std::vector<std::string> &s) {
    // std::cerr << "Before: ";
    // for(int i = 0; i < s.size(); ++i) std::cerr << s[i] << char(i == s.size() - 1 ? 10 : 32);
    // std::cerr << std::flush;
    int pos = -1, type = 0;
    for(int i = s.size() - 1; i >= 3; --i) {
        if(s[i][0] == s[i - 3][0] && type < 4)
            pos = i, type = 4;
        if(s[i][1] == s[i - 3][1] && type < 2)
            pos = i, type = 2;
    }
    if(type == 4)
        s.erase(s.begin() + (pos - 3), s.begin() + (pos + 1));
    if(type == 2)
        s.erase(s.begin() + (pos - 3)),
        s.erase(s.begin() + (pos - 1));
    // std::cerr << "After: ";
    // for(int i = 0; i < s.size(); ++i) std::cerr << s[i] << char(i == s.size() - 1 ? 10 : 32);
    // std::cerr << std::flush;
    return type > 0;
}

int main() {
    std::vector<std::string> deck(52), st;
    for(auto &card: deck) std::cin >> card;
    for(auto card: deck) {
        st.push_back(card);
        while(shrink(st));
    }
    std::cout << st.size();
    for(int i = 0; i < st.size(); ++i) std::cout << char(32) << st[i];
    std::cout << std::endl;
    return 0;
}

K. Two Charts Become One

因为没判两个树都是单点的Corner Case红温了好久,浪费了好多时间

根据题目中对于树的同构的定义,其实只要判每个点的儿子按顺序重排后是否相同即可

更方便的写法是直接把每条边按照父亲到儿子的顺序加入集合中,最后比较两个数对应的边集合是否相同即可

然后注意下模拟建树的过程即可,由于只有一个点的时候不存在边因此可以假设一个编号为\(0\)的虚点套在最外层

#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
#include<set>
#include<cctype>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
string A,B;
inline vector <pi> solve(string s)
{
	RI i,j; string t=""; vector <pi> edges;
	for (i=0;i<s.size();++i) if (!isspace(s[i])) t+=s[i];
	t="(0("+t+"))"; stack <int> stk; set <pi> rst;
	for (i=0;i<t.size();++i)
	{
		if (t[i]=='(') { stk.push(i); continue; }
		if (t[i]==')')
		{
			int pos=stk.top(); stk.pop();
			int x=0; for (j=pos+1;;++j)
			if (isdigit(t[j])) x=x*10+t[j]-'0'; else break;
			for (auto it=rst.upper_bound(pi(pos,0));it!=rst.end();it=rst.erase(it))
			edges.push_back(pi(x,it->se));
			rst.insert(pi(pos,x)); continue;
		}
	}
	sort(edges.begin(),edges.end());
	return edges;
}
int main()
{
	ios::sync_with_stdio(false); cin.tie(0);
	getline(cin,A); getline(cin,B);
	return puts(solve(A)==solve(B)?"Yes":"No"),0;
}

L. Which Warehouse?

很裸的一个题

由于每个点不能选两种及以上的物资,因此我们可以把问题转化为一个二分图最小权匹配问题

左边\(n\)个点代表原图中的点,右边\(m\)个点代表物资,两点间连边对应将所有该类物资移动到对应点上的代价和,这个可以预处理最短路后快速计算

然后直接上KM即可,注意KM要求二分图两边点的数量相同,这点也很好解决,直接在右边多开\(n-m\)个点,表示对应点不作为存储地点,与左边所有点的边权都是\(0\)即可

#include<cstdio>
#include<iostream>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=105,INF=1e18;
int n,m,c[N][N],dis[N][N];
namespace KM
{
	int w[N][N],kx[N],ky[N],py[N],vy[N],slk[N],pre[N];
	inline int solve(CI n)
	{
		RI i,j,k; for (i=1;i<=n;++i) for (j=1;j<=n;++j) kx[i]=max(kx[i],w[i][j]);
		for (i=1;i<=n;++i)
		{
			for (j=0;j<=n;++j) vy[j]=pre[j]=0,slk[j]=INF;
			int k=0,p=-1; for (py[k=0]=i;py[k];k=p)
			{
				int d=INF; vy[k]=1; int x=py[k];
				for (j=1;j<=n;++j) if (!vy[j])
				{
					int t=kx[x]+ky[j]-w[x][j];
					if (t<slk[j]) slk[j]=t,pre[j]=k;
					if (slk[j]<d) d=slk[j],p=j;
				}
				for (j=0;j<=n;++j)
				if (vy[j]) kx[py[j]]-=d,ky[j]+=d; else slk[j]-=d;
			}
			for (;k;k=pre[k]) py[k]=py[pre[k]];
		}
		int ret=0; for (i=1;i<=n;++i) ret+=kx[i]+ky[i];
		return -ret;
	}
};
using namespace KM;
signed main()
{
	RI i,j,k; for (scanf("%lld%lld",&n,&m),i=1;i<=n;++i)
	for (j=1;j<=m;++j) scanf("%lld",&c[i][j]);
	for (i=1;i<=n;++i) for (j=1;j<=n;++j)
	if (scanf("%lld",&dis[i][j]),dis[i][j]==-1) dis[i][j]=INF;
	for (k=1;k<=n;++k) for (i=1;i<=n;++i) for (j=1;j<=n;++j)
	dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
	for (i=1;i<=n;++i) for (j=1;j<=m;++j)
	{
		int cur=0; for (k=1;k<=n;++k) cur+=dis[k][i]*c[k][j];
		w[i][j]=-cur;
	}
	return printf("%lld",solve(n)),0;
}

Postscript

每天被花式腐乳,真是菜菜又鸡鸡啊

标签:std,cnt,America,Central,int,2022,const,include,define
From: https://www.cnblogs.com/cjjsb/p/18003700

相关文章

  • vs2022支持c++20 import模块功能
    参考链接:https://blog.csdn.net/fellow1984/article/details/124819231工具->获取工具和功能->VisualStudioInstaller->单个组件:搜索C++模块,勾选项目属性对应项修改编译代码即可//helloworldimport<iostream>;intmain(){ std::cout<<"helloworld\n";......
  • 李宏毅《机器学习》总结 - 2022 HW3(图像识别、CNN) Strong Baseline
    调参调吐了。。最好做到了private0.82/public0.808这题前前后后做了五天。。主要是后来train一次就得花很长很长时间,我的kaggle余额也用的差不多了。。这个题目大概就是给你11种食物的图片,让你学习,并分类CNN处理图片就先转化成\(128\times128\)个pixel,然后做......
  • P8353 [SDOI/SXOI2022] 无处存储
    存下每个点的父亲信息\(fa\)和点权\(w\)就已经用去近\(54\text{MiB}\)了,树剖似得彻彻底底。考虑树分块:随机选定\(\sqrtn\)个点作为关键点建虚树,这样每个点向上走到关键点的步数期望为\(\sqrtn\),然后每个关键点存原树上从它到它虚树上的父亲结点的信息。dfs似了,......
  • Windows server 2022 安全基线加固 安全加固 仅供参考
    WindowsRegistryEditorVersion5.00[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer\WinStations\RDP-Tcp]"PortNumber"=dword:0000045a[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]"Dis......
  • [NOI2022] 移除石子
    [NOI2022]移除石子题目描述你正在玩一个名为“移除石子”的小游戏。有\(n\)堆石子排成一行,第\(i\)堆有\(a_i\)枚,你的任务是通过如下的操作将所有石子移除:操作一:选择一堆石子,将其中的至少\(2\)枚石子移除;操作二:选择一个连续的编号区间\([l,r]\)(\(1\lel\ler\l......
  • Visual Studio 2022 + Qt 中文乱码问题
    使用Qt编译中文标题出现乱码问题如下图首先打开文件属性->点击(C/C++)->点击(所有选项)->找到(附加选项)这一栏修改为(/UTF-8)注意大小写  然后在头文件中添加以下代码:1#if_MSC_VER>=16002#pragmaexecution_character_set("utf-8")3#endif即可解决问题......
  • P8352 [SDOI/SXOI2022] 小 N 的独立集
    还是先打暴力,枚举\(k^n\)种树的形态做树形DP,时间复杂度\(\mathcalO(nk^n)\),拿下\(n\le8\)和\(k=1\)的\(25\)分。虽然很简单,还是交代下吧:设\(f(u,0/1)\)表示以\(u\)为根的子树中是否选\(u\)的最大权独立集,\(f(u,0)\getsw_u+\sum\limits_{v\inson_u}......
  • (二)VS2022启动项目调试显示“正在加载......的符号”的解决方法
    之前重来没有遇到过的问题,自从安装了VS2022后,每次调试都会显示“正在加载......”的弹框,虽然对程序没有多大影响,但是这种体验非常不友好,于是找了许多方法,下面是亲测有效的方法:一、检查“工具”》“选项”》“调试”》“符号”是否去√。二、检查“工具”》“选项”》“调试”......
  • P8350 [SDOI/SXOI2022] 进制转换
    记\(len_x\)为\(x\)在\(a\)中出现的次数,显然有\(\mathcalO(nq)\)的暴力,拿下\(20\)分。感觉用数据结构难以维护,考虑根号做法。根号做法有一个阈值\(L\),然后分讨(钦定\(len_x\lelen_y\)):\(len_x\lelen_y\leL\)直接暴力做,时间复杂度\(\mathcalO(L)\)。\(L......
  • IDEA2022 解决每次启动新项目maven配置就变为C盘问题
    1、打开一个空的IDEA如果打开IDEA默认进入之前的项目,可以选择先Closeproject退出项目 2、选择左侧的Customize,再点击Configure 3、在打开的Setting设置里面找到Maven配置Build,Execution,Deployment->BuildTools->Maven 修改后,保存即可; ......