11.27 noip模拟赛

信心赛,又双叒叕挂分了……

T1

打表,未果,寻洪文,后遂无问津者

然后很唐的对着错误的大样例调了半天

后来小 L 从我身后经过,说:“这大样例是假的,你再说,假吗

发现如果当前钱数 \(>ax\) 那么买 \(a\) 瓶又获得 \(b\) 元等价于花费 \(ax-b\)

然后就可以 \(O(1)\) 求出买几个 \(ax\) 捆绑套餐,然后剩的钱单独算一下即可

赛后发现挂分了

因为我写的是向上取整,但是正解是向下取整再加一

因为你剩的钱完全够再买一次,所以 \(100 \rightarrow 40\)

点击查看代码
#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;

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;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}

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

int n,a,b,v;

void Main()
{
	n=read(),v=read(),a=read(),b=read();
	if(n>=v*a&&b>=v*a)
	{
		printf("-1\n");
		return;
	}
	if(n<v*a||b==0)
	{
		printf("%lld\n",n/v);
	}
	else
	{
		int del=v*a-b;
		int k=(n-v*a)/del+1;
		int ans=k*a+(n-k*del)/v;
		printf("%lld\n",ans);
	}
}

signed main()
{
#define FJ
#ifdef FJ
	freopen("buy.in","r",stdin);
	freopen("buy.out","w",stdout);
#else
	freopen("buy2.in","r",stdin);
	freopen("buy.out","w",stdout);
#endif
	
	int T=read();
	while(T--) Main();
	
	return 0;
}

T2

很唐啊,我判的是这个点能否当重叠点,但是是假的

因为转移的时候可能那个块挤不过去,然后就被 HACK 了,而且还有可恶的 \(\text{Subtask}\)

正解其实跟我差不多,就是能转移的话把点入队,跑 BFS 即可

(但是你这题为什么要先读 \(m\) 再读 \(n\),先读 \(y\) 再读 \(x\),还有这个图片纯误导人,\(k1\)\(k2\) 读反都能过)

然鹅我的假算法在 \(\text{Subtask}\) 的情况下还有 \(27\)

点击查看代码
#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;

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;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}

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

bool vis[N][N];
int u[N][N],d[N][N],l[N][N],r[N][N];
int h,w,k1,k2;
char mp[N][N];
int stx,sty,edx,edy;

struct node{int x,y;};
inline bool operator<(node xx,node yy)
{
	return abs(edx-xx.x)+abs(edy-xx.y)>abs(edx-yy.x)+abs(edy-yy.y);
}
int dx[]={0,0,0,1,-1},dy[]={0,1,-1,0,0};
priority_queue<node> q;

signed main()
{
#define FJ
#ifdef FJ
	freopen("puzzle.in","r",stdin);
	freopen("puzzle.out","w",stdout);
#else
//	freopen("puzzle3.in","r",stdin);
//	freopen("puzzle.out","w",stdout);
#endif
	
	w=read(),h=read(),k1=read(),k2=read();
	read();
	stx=read()+1;
	sty=read()+1;
	read();
	
	fd(i,1,h)
	{
		fd(j,1,w)
		{
			cin>>mp[i][j];
			if(mp[i][j]=='*') edx=i,edy=j;
		}
	}
	
	fd(i,1,h)
	{
		int L=1,R=1;
		while(R<=w)
		{
			while(mp[i][L]=='X'&&L<=w) ++L;
			if(L>w) break;
			R=L;
			while(mp[i][R+1]!='X'&&R<w) ++R;
			fd(j,L,R) l[i][j]=L,r[i][j]=R;
			L=R+1;
			if(L>w) break;
		}
	}
	
	fd(i,1,w)
	{
		int L=1,R=1;
		while(R<=h)
		{
			while(mp[L][i]=='X'&&L<=h) ++L;
			if(L>h) break;
			R=L;
			while(mp[R+1][i]!='X'&&R<h) ++R;
			fd(j,L,R) u[j][i]=L,d[j][i]=R;
			L=R+1;
			if(L>h) break;
		}
	}
	
//	fd(x,1,h)
//	fd(y,1,w)
//	{
//		cerr<<x<<' '<<y<<endl;
//		cerr<<u[x][y]<<' '<<d[x][y]<<endl;
//		cerr<<l[x][y]<<' '<<r[x][y]<<endl;
//		cerr<<endl;
//	}
	
	q.push({stx,sty});
	while(!q.empty())
	{
		int x=q.top().x,y=q.top().y;q.pop();
//		cerr<<x<<' '<<y<<endl;
//		cerr<<u[x][y]<<' '<<d[x][y]<<endl;
//		cerr<<l[x][y]<<' '<<r[x][y]<<endl;
		vis[x][y]=1;
		if(x==edx&&y==edy)
		{
			cout<<"YES";
			return 0;
		}
		fd(i,1,4)
		{
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<1||ny<1||nx>h||ny>w||vis[nx][ny]||mp[nx][ny]=='X') continue;
			if(min(r[x][y],r[nx][ny])-max(l[x][y],l[nx][ny])+1<k1)
			{
//				cerr<<"#1 "<<r[nx][ny]<<' '<<l[nx][ny]<<' '<<min(r[x][y],r[nx][ny])-max(l[x][y],l[nx][ny])+1<<endl;
				continue;
			}
			if(min(d[x][y],d[nx][ny])-max(u[x][y],u[nx][ny])+1<k2)
			{
//				cerr<<"#2 "<<u[nx][ny]<<' '<<d[nx][ny]<<' '<<min(d[x][y],d[nx][ny])-max(u[x][y],u[nx][ny])+1<<endl;
				continue;
			}
			vis[nx][ny]=1,q.push({nx,ny});
		}
	}
	
	cout<<"NO";
	
	return 0;
}

T3

发现保留最短路上的点最优

但是我根本没想到什么最小生成树枚举树根

我想的是保留的一定是重叠的,并且都在根节点到 \(s1,s2\) 最短路上的一部分共同边再加上向 \(s1\)\(s2\) 的分叉

然后我跑 DFS,居然过了,而且跑得飞快,我甚至没加记忆化(

正解是枚举树根,算到 \(1,s1,s2\) 三点的距离和并取 \(\min\)

点击查看代码
#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;

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;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}

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

int n,m,s1,s2,t1,t2;
vector<int> e[N];
int d[3][N],vis[N];
priority_queue< pair<int,int> > q;

int ans,mx;

void dij(int op)
{
	memset(d[op],0x3f,sizeof(d[op]));
	memset(vis,0,sizeof(vis));
	int s;
	if(op==0) s=1;
	if(op==1) s=s1;
	if(op==2) s=s2;
	d[op][s]=0;
	q.push({0,s});
	while(!q.empty())
	{
		int x=q.top().second;q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(auto &y:e[x])
		{
			if(d[op][y]>d[op][x]+1)
			{
				d[op][y]=d[op][x]+1;
				q.push({-d[op][y],y});
			}
		}
	}
}

void dfs(int x,int len,int fa)
{
	mx=max(mx,len);
	for(auto &y:e[x])
	{
		if(y==fa) continue;
		if(d[0][x]+1+d[1][y]==d[0][s1]&&d[0][x]+1+d[2][y]==d[0][s2])
		{
			dfs(y,len+1,x);
		}
	}
}

signed main()
{
#define FJ
#ifdef FJ
	freopen("boom.in","r",stdin);
	freopen("boom.out","w",stdout);
#else
	freopen("boom3.in","r",stdin);
	freopen("boom.out","w",stdout);
#endif
	
	n=read(),m=read();
	fd(i,1,m)
	{
		int x=read(),y=read();
		e[x].push_back(y);
		e[y].push_back(x);
	}
	s1=read(),t1=read(),s2=read(),t2=read();
	
	dij(0),dij(1),dij(2);
	
	if(d[0][s1]>t1||d[0][s2]>t2)
	{
		puts("-1");
		return 0; 
	}
	
	ans=d[0][s1]+d[0][s2];
	
	dfs(1,0,0);
	
	printf("%lld",m-(ans-mx));
	
	return 0;
}

T4

DP 题,但是赛时写的 \(O(n m^n)\) 的暴力 T 了

然后记 \(f_{i,j,k,l}\) 表示前 \(i\) 位,确定了 \(j\) 个数,有 \(k\)\(1\),向后的进位是 \(l\) 的总和

然后转移是枚举 \(a_j=i\) 的个数,令其为 \(t\)

那么可以转移:

\[f_{i+1,j+t,k+(t+l)\mod 2,\lfloor \frac{t+l}{2} \rfloor}+=f_{i,j,k,l}\times v_i^t \times C_{t}^{n-j} \]

然后就做完了

点击查看代码
#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;
		
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;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}
		
const int N=35,M=109,mod=998244353;
		
int n,m,K;
int f[M][N][N][N],v[M],c[N][N];
		
inline int qpow(int x,int y)
{
	int re=1;
	while(y)
	{
		if(y&1) (re*=x)%=mod;
		(x*=x)%=mod,y>>=1;
	}
	return re;
}
		
inline int popcont(int x)
{
	int cnt=0;
	while(x) ++cnt,x-=x&-x;
	return cnt;
}
		
signed main()
{
#define FJ
#ifdef FJ
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
#else
//	freopen("count2.in","r",stdin);
//	freopen("count.out","w",stdout);
#endif
	
	n=read(),m=read(),K=read();
	fd(i,0,m) v[i]=read();
	
	c[0][0] = 1;
	fd(i,1,31)
	{
		c[i][0]=1;
		fd(j,1,i) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
	}
	
	f[0][0][0][0]=1;
	fd(i,1,n) f[0][i][i&1][i/2]=c[n][i]*qpow(v[0],i)%mod;
	
	fd(i,0,m-1) fd(j,0,n) fd(k,0,K) fd(p,0,n/2) fd(q,0,n-j)
		if(f[i][j][k][p]) (f[i+1][q+j][k+((p+q)&1)][(p+q)/2]+=(f[i][j][k][p]*qpow(v[i+1],q)%mod*c[n-j][q]%mod))%=mod;
	
	int ans=0;
	fd(k,0,K) fd(p,0,n/2)
		if(k+popcont(p)<=K) (ans+=f[m][n][k][p])%=mod;
	
	printf("%lld",ans);
	
	return 0;
}
posted @   whrwlx  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示