11.23 NOIP2024模拟赛#27

又㕛叒叕挂分力

T1

好诈骗啊

开始发现相邻两项相差应该不大,然后猜最大是 \(20\)

但是大样例 T 了

后来发现是纯贪,但是码了好久

点击查看代码
//贪

#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;

//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
template<typename _T=int>
inline _T read()
{
	_T x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
	return x*f;
}

const int N=5e3+509,M=1e6+509,mod=998244353;

int n,m;
int p[N],c[N];
vector<int> res;
int vis[N];

inline bool check(int x,int l,int r,int lst,int s)
{
	int val=0;
	val=min((p[x]-l)*2+r-p[x],(r-p[x])*2+p[x]-l)+s;
//	cerr<<val<<endl;
	if(lst) val+=abs(p[lst]-p[x]);
//	cerr<<x<<' '<<l<<' '<<r<<' '<<lst<<' '<<s<<':'<<val<<endl;
	return val<=m;
}

void dfs(int x,int lst,int s)
{
//	cerr<<x<<' '<<l<<' '<<r<<' '<<lst<<' '<<s<<endl;
	if(x>n)
	{
		for(auto &j:res) printf("%lld ",j);
		exit(0);
	}
	int l=1e18,r=0;
	fd(i,1,n)
	{
		if(vis[i]) continue;
		l=min(p[i],l),r=max(p[i],r);
	}
	fd(y,1,n)
	{
		if(vis[y]) continue;
		if(check(y,l,r,lst,s))
		{
			vis[y]=1,res.push_back(y);
			dfs(x+1,y,s+(lst!=0)*abs(p[y]-p[lst]));
			vis[y]=0,res.pop_back();
		}
	}
}

signed main()
{
#define FJ
#ifdef FJ
	freopen("hamilton.in","r",stdin);
	freopen("hamilton.out","w",stdout);
#else
	freopen("ex_hamilton3.in","r",stdin);
	freopen("hamilton.out","w",stdout);
#endif
//#define io
#ifdef io
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
#endif
	
	n=read(),m=read();
	fd(i,1,n)
	{
		int x=read();
		c[i]=read(),p[c[i]]=x;
	}
	if(m<p[c[n]]-p[c[1]])
	{
		printf("-1");
		return 0;
	}
	
	dfs(1,0,0);
	printf("-1");
	
	return 0;
}

T2

码的 \(x\le 5000\) 暴力,记两个指针然后预处理即可

然后全是 \(a\) 的可以推柿子,然鹅我向上取整然后 WA 了

赛时打表,发现答案很有规律

所以应该是找循环节,但是我不会(

正解是找完循环节然后二分

T3

题看的头晕,是模拟

但是感觉很麻烦而且估计有 \(\text{Subtask}\) 然后就没敢写

正解理论是剪一些情况,但是纯暴力的话手动开 \(O3\) 可以卡过去(

实际上赛后 \(20min\) 就码完了

点击查看代码
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<vector>
#include<iostream>
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'

//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
	return x*f;
}

const int N=15;

std::vector<std::pair<int,int> >ans;
int cnt[15][15];
char s[N];

inline void getcnt()
{
	scanf("%s",s+1);
	int ch=s[1]-'0';
	if(s[2]=='m') ++cnt[ch][1];
	if(s[2]=='s') ++cnt[ch][2];
	if(s[2]=='p') ++cnt[ch][3];
	if(s[2]=='c') ++cnt[ch][4];
}

bool ck()
{
	int res=0,cntt[15];
	fd(i,1,3)
	{
		fd(j,1,9) cntt[j]=cnt[j][i];
		cntt[10]=cntt[11]=0;
		fd(j,1,9)
		{
			int md=cntt[j]%3;
			if(cntt[j+1]<md||cntt[j+2]<md) return 0;
			cntt[j]-=md,cntt[j+1]-=md,cntt[j+2]-=md;
			res+=md+(cntt[j]/3);
			if(res>=4) return 1;
		}
	}
	fd(i,1,7)
		if(cnt[i][4]>=3)
			if(++res>=4) return 1;
	return res>=4;
}

void check(int x,int id)
{
	if(cnt[1][1]&&cnt[9][1]&&cnt[1][2]&&cnt[9][2]&&cnt[1][3]&&cnt[9][3]&&cnt[1][4]&&cnt[2][4]&&cnt[3][4]&&cnt[4][4]&&cnt[5][4]&&cnt[6][4]&&cnt[7][4])
		if(cnt[1][1]>=2||cnt[9][1]>=2||cnt[1][2]>=2||cnt[9][2]>=2||cnt[1][3]>=2||cnt[9][3]>=2||cnt[1][4]>=2||cnt[2][4]>=2||cnt[3][4]>=2||cnt[4][4]>=2||cnt[5][4]>=2||cnt[6][4]>=2||cnt[7][4]>=2)
			{ans.push_back({x,id});return;}
	fd(i,1,4)
	{
		fd(j,1,i==4?7:9)
		{
			if(cnt[j][i]>=2)
			{
				cnt[j][i]-=2;
				if(ck()) {ans.push_back({x,id}),cnt[j][i]+=2;return;}
				cnt[j][i]+=2;
			}
		}
	}
}

signed main()
{
#define FJ
#ifdef FJ
	freopen("mahjong.in","r",stdin);
	freopen("mahjong.out","w",stdout);
#else
//	freopen("A.in","r",stdin);
//	freopen("A.out","w",stdout);
#endif
//#define io
#ifdef io
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
#endif
	
	int T=read();
	while(T--)
	{
		ans.resize(0);
		int sum=0;
		fd(i,1,4) fd(j,1,i==4?7:9) cnt[j][i]=0;
		fd(i,1,13) getcnt();
		fd(i,1,4) fd(j,1,i==4?7:9) if(cnt[j][i]>=2) ++sum;
		fd(i,1,4)
		{
			fd(j,1,i==4?7:9)
			{
				if(cnt[j][i]==1&&sum>=6)
					ans.push_back({j,i});
				else if(cnt[j][i]<4)
					++cnt[j][i],check(j,i),--cnt[j][i];
			}
		}
		if(ans.empty())
		{
			puts("Nooten");
			continue;
		}
		printf("%d ",(int)ans.size());
		for(const auto &i:ans)
		{
			printf("%d",i.first);
			if(i.second==1) putchar('m');
			if(i.second==2) putchar('s');
			if(i.second==3) putchar('p');
			if(i.second==4)	putchar('c');
			putchar(' ');
		}
		putchar('\n');
	}
	
	return 0;
}

T4

开始看错题了,以为是区间修改,但是是全部修改,然后码了 \(300\) 多行的分块(

最后写的暴力

正解是倒着操作,然后上线段树即可

总结

  • 如果不管 T4 正解而去写 T3 的话也许可以多 \(60\) ~ \(100\)
  • T2 挂 \(20\)
  • T4 真没想到可以倒着操作
posted @ 2024-11-24 15:01  whrwlx  阅读(0)  评论(0编辑  收藏  举报