20240324比赛总结

T1 卫星照片

https://gxyzoj.com/d/hzoj/p/3657

bfs暴力找联通块,再暴力判断即可

因为某些原因代码丢了,就不放了

T2 [luogu3802]小魔女帕琪

https://gxyzoj.com/d/hzoj/p/3656

考虑到,前7个均不同的概率为\(\prod_{i=1}^{7} \dfrac{a_i}{sum+1-i}\times 7!\)

因为每种情况均有\(\prod_{i=1}^{7} \dfrac{a_i}{sum+1-i}\)种,每个情况等概率出现,所以乘7!

接着考虑后面的情况,以第二个为例,方案数为:

\[\frac{a_1}{sum}\times 7!\times(\frac{a_1-1}{sum-1}+\frac{a_2}{sum-2}+\dots+\frac{a_7}{sum-7})+\frac{a_2}{sum}\times 7!\times(\frac{a_1}{sum-1}+\frac{a_2-1}{sum-2}+\dots+\frac{a_7}{sum-7})+\dots+\frac{a_7}{sum}\times 7!\times(\frac{a_1}{sum-1}+\frac{a_2}{sum-2}+\dots+\frac{a_7-1}{sum-7}) \]

化简得:\(\prod_{i=1}^{7} \dfrac{a_i}{sum+1-i}\times 7!\)

所以答案为:\(\prod_{i=1}^{7} \dfrac{a_i}{sum+1-i}\times 7!\times (sum-6)\)

代码:

#include<cstdio>
using namespace std;
int a[10],n;
double ans=1.0;
int main()
{
	for(int i=1;i<=7;i++)
	{
		scanf("%d",&a[i]);
		n+=a[i];
		ans*=a[i]*i;
	}
	for(int i=0;i<=5;i++)
	{
		ans/=1.0*(n-i);
	}
	printf("%.3lf",ans);
	return 0;
}

T3 [NOIP2016 普及组] 魔法阵

https://gxyzoj.com/d/hzoj/p/3655

\(X_d-X_c=t\),则\(X_b-X_a=2t\)

因为\(X_b-X_a>(X_c-X_b)/3\),所以\(X_c-X_b>6t\),故\(X_c=X_b+6t+k\)

可以枚举\(t,k,X_d\),考虑优化

枚举\(X_d,t\),因为若\(X_a,X_b\)满足条件,则\(X_a-1,X_b-1\)一定满足,所以可以用前缀和记录\(X_a\times X_b\)即可

同理枚举\(X_a,t\),求\(ans_a,ans_b\)

代码:

#include<cstdio>
using namespace std;
int n,m,val[40004],cnt[15005],A[15005],B[15005],C[15005],D[15005];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&val[i]);
		cnt[val[i]]++;
	}
	for(int t=1;t*9<=n;t++)
	{
		int sum=0;
		for(int d=t*9+2;d<=n;d++)
		{
			int a=d-t*9-1;
			int b=a+2*t;
			int c=d-t;
			sum+=cnt[a]*cnt[b];
			C[c]+=sum*cnt[d];
			D[d]+=sum*cnt[c];
		}
		sum=0;
		for(int a=n-t*9-1;a>0;a--)
		{
			int b=a+2*t;
			int d=a+t*9+1;
			int c=b+6*t+1;
			sum+=cnt[d]*cnt[c];
			A[a]+=sum*cnt[b];
			B[b]+=sum*cnt[a];
		}
	}
	for(int i=1;i<=m;i++)
	{
		printf("%d %d %d %d\n",A[val[i]],B[val[i]],C[val[i]],D[val[i]]);
	}
	return 0;
}

T4 [HAOI2016] 字符合并

https://gxyzoj.com/d/hzoj/p/3298

看到数据范围,考虑区间dp+状压dp,设\(dp_{i,j,s}\)表示区间[i,j],合并后状态为s的最大值

因为最优的情况一定是将所有能合并的合并,且若暴力枚举断点,一定会T,考虑优化

1个字符可以不操作,m个连续字符可以合并成1个字符,于是得到\(x\times(m−1)+1\)个连续字符,能合并成一个字符。

所以,可以枚举所有能转移的点k求最大值,但当\((r-l)\equiv 0(\bmod m-1)\)时,要考虑\(dp_{l,r,0}=max(dp_{l,r,0}+w_s*[s=0])\),\(dp_{l,r,1}=max(dp_{l,r,1}+w_s*[s=1])\)

代码:

#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,a[305],c[305];
ll w[305],dp[305][305][305],g[5];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int s=0;s<(1<<m);s++)
			{
				dp[i][j][s]=-2e9; 
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		dp[i][i][a[i]]=0;
	}
	for(int i=0;i<(1<<m);i++)
	{
		scanf("%d%lld",&c[i],&w[i]);
	}
	for(int len=2;len<=n;len++)
	{
		for(int i=1;i+len-1<=n;i++)
		{
			int j=i+len-1;
			int tmp=(len-1)%(m-1);
			if(tmp==0&&len!=1) tmp=m-1;
			for(int k=j;k>i;k=k-m+1)
			{
				for(int s=0;s<(1<<(tmp+1));s++)
				{
					dp[i][j][s<<1]=max(dp[i][k-1][s]+dp[k][j][0],dp[i][j][s<<1]);
					dp[i][j][s<<1|1]=max(dp[i][k-1][s]+dp[k][j][1],dp[i][j][s<<1|1]);
				}
			}
			if(tmp==m-1)
			{
				g[1]=g[0]=-2e9;
				for(int s=0;s<(1<<m);s++)
				{
					g[c[s]]=max(g[c[s]],dp[i][j][s]+w[s]);
				}
				dp[i][j][0]=g[0],dp[i][j][1]=g[1];
			}
		}
	}
	ll ans=-9e18;
	for(int i=0;i<(1<<m);i++)
	{
		ans=max(ans,dp[1][n][i]);
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2024-03-26 20:05  wangsiqi2010916  阅读(42)  评论(0编辑  收藏  举报