2020级训练赛10.28

最大子矩阵

一、题目

点此看题

二、解法

d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]为第一列选 i i i个,第二列选 j j j个,选出 k k k个矩形的最大得分。

{ d p [ i ] [ j ] [ k ] = d p [ i − 1 ] [ j ] [ k ] ( i > 0 ) d p [ i ] [ j ] [ k ] = d p [ i ] [ j − 1 ] [ k ] ( j > 0 ) d p [ i ] [ j ] [ k ] = d p [ p ] [ j ] [ k − 1 ] + p 1 [ i ] − p 1 [ p ] ( p < i ) d p [ i ] [ j ] [ k ] = d p [ i ] [ p ] [ k − 1 ] + p 2 [ i ] − p 2 [ p ] ( p < j ) d p [ i ] [ j ] [ k ] = d p [ p ] [ p ] [ k − 1 ] + p 1 [ i ] − p 1 [ p ] + p 2 [ i ] − p 2 [ p ] ( i = j   ∧   p < i ) \begin{cases} dp[i][j][k]=dp[i-1][j][k] & (i>0) \\ dp[i][j][k]=dp[i][j-1][k] & (j>0) \\ dp[i][j][k]=dp[p][j][k-1]+p1[i]-p1[p] & (p<i)\\ dp[i][j][k]=dp[i][p][k-1]+p2[i]-p2[p] & (p<j)\\ dp[i][j][k]=dp[p][p][k-1]+p1[i]-p1[p]+p2[i]-p2[p] & (i=j \space \wedge \space p<i) \end{cases} dp[i][j][k]=dp[i1][j][k]dp[i][j][k]=dp[i][j1][k]dp[i][j][k]=dp[p][j][k1]+p1[i]p1[p]dp[i][j][k]=dp[i][p][k1]+p2[i]p2[p]dp[i][j][k]=dp[p][p][k1]+p1[i]p1[p]+p2[i]p2[p](i>0)(j>0)(p<i)(p<j)(i=j  p<i)

这样我们就得到了一个 O ( n 3 k ) O(n^3k) O(n3k)的算法。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int read()
{
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int n,m,k,p1[105],p2[105];
int f[105][11],dp[105][105][11];
int main()
{
	n=read();m=read();k=read();
	for(int i=1;i<=n;++i)
	{
		p1[i]=p1[i-1]+read();
		if(m==2)p2[i]=p2[i-1]+read();
	}
	dp[0][0][0]=0;
	for(int l=1;l<=k;l++)
		for(int i=0;i<=n;i++)
			for(int j=0;j<=n;j++)
			{
				if(!i && !j) continue;
				if(i)dp[i][j][l]=dp[i-1][j][l];
				if(j)dp[i][j][l]=max(dp[i][j-1][l],dp[i][j][l]);
				for(int p=0;p<i;p++)
					dp[i][j][l]=max(dp[i][j][l],dp[p][j][l-1]+p1[i]-p1[p]);
				for(int p=0;p<j;p++)
					dp[i][j][l]=max(dp[i][j][l],dp[i][p][l-1]+p2[j]-p2[p]);
				if(i==j)
					for(int p=0;p<i;p++)
						dp[i][j][l]=max(dp[i][j][l],dp[p][p][l-1]+p1[i]-p1[p]+p2[j]-p2[p]);
			}
	printf("%d\n",dp[n][n][k]);
}

序列的第 k 个数

一、题目

点此看题

二、解法

签到题,实在太水了。

#include <cstdio>
#define int long long
#define mod(x) ((x)%MOD+MOD)%MOD
const int MOD = 200907; 
int read()
{
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int T,a,b,c,k;
int qkpow(int a,int b)
{
	int res=1;
	while(b>0)
	{
		if(b&1) res=res*a%MOD;
		a=a*a%MOD;
		b>>=1; 
	}
	return res;
}
signed main()
{
	T=read();
	while(T--)
	{
		a=read();b=read();c=read();k=read();
		if(b-a==c-b)
		{
			printf("%d\n",mod(a+(k-1)*(b-a)));
			continue;
		}
		int d=b/a;
		printf("%d\n",mod(a*qkpow(d,k-1)));
	}
}

Star Way To Heaven

一、题目

点此看题

二、解法

考虑二分答案 t t t,以每个星星为圆心作圆,然后就是看从 x x x轴开始每次走不超过 2 t 2t 2t走到上顶面,也就是考虑星星能不能封路,时间复杂度 O ( k 2 log ⁡ m ) O(k^2\log m) O(k2logm)
发现可以建一棵最小生成树(这里的说法不是很严谨,应该生成到上下联通),然后取最大的边即可,时间复杂度 O ( k 2 ) O(k^2) O(k2)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
#define int long long
const int MAXN = 6005;
int read()
{
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int n,m,k,ans,x[MAXN],y[MAXN],dis[MAXN];
int dist(int i,int j)
{
	return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
signed main()
{
	n=read();m=read();k=read();
	for(int i=1;i<=k;i++)
		x[i]=read(),y[i]=read();
	memset(dis,0x3f,sizeof dis);
	dis[k+2]=0;
	for(int i=1;i<=k+2;i++)
	{
		int id=0;
		for(int j=1;j<=k+2;j++)
		{
			if(dis[id]>dis[j] && dis[j]!=-1)
				id=j;
		}
		ans=max(ans,dis[id]);
		if(id==k+1) break;
		dis[id]=-1; 
		for(int j=1;j<=k+1;j++)
		{
			if(j==k+1) dis[j]=min(dis[j],(m-y[id])*(m-y[id]));
			else if(id==k+2) dis[j]=min(dis[j],y[j]*y[j]);
			else dis[j]=min(dis[j],dist(id,j));
		}
	}
	printf("%.9lf",sqrt(ans)*0.5);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值