2月4日题解

本文解析了CodeForces平台上的两道经典算法题目:1060C最大子矩形与122D幸运转换。针对1060C题,通过前缀和与动态规划策略找出内部元素和不超过x的矩形最大面积;对于122D题,则通过状态判断和操作计数策略解决字符串转换问题。

A题 CodeForces - 1060C Maximum Subrectangle

题意:输入n,m以及两个长度分别为n和m的数组A和B,这两个数组分别是二维数组C的第一行和第一列,其余元素遵循Ci,j=Ai*Bj。再输入一个整数x。在二维数组C中找内部元素和不大于x的矩形,求矩形的最大面积。
思路:首先搞清楚一个规律:对于任意一个子矩阵(l1…r1)(l2…r2),其内部元素和等于(a[l1]+a[l1+1]+…a[r1])x(b[l2]+b[l2+1]+…+b[r2])。所以需要前缀和处理计算各部分元素和。(ma[i]:表示在数组a中长度为i的子数组元素和最小值)然后用两个数组ma和mb找到子数组元素和最小值,然后枚举两数组长度即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
ll n,m,x,ans,a[2010],b[2010],sa[2010],sb[2010],ma[2010],mb[2010];
int main(){
	scanf("%lld %lld",&n,&m);
	sa[0]=sb[0]=0;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		sa[i]=sa[i-1]+a[i];
	}
	for(int i=1;i<=m;i++){
		scanf("%lld",&b[i]);
		sb[i]=sb[i-1]+b[i];
	}
	memset(ma,inf,sizeof(ma));
	memset(mb,inf,sizeof(mb));
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			ma[j-i+1]=min(ma[j-i+1],sa[j]-sa[i-1]);
		}
	}
	for(int i=1;i<=m;i++){
		for(int j=i;j<=m;j++){
			mb[j-i+1]=min(mb[j-i+1],sb[j]-sb[i-1]);
		}
	}
	scanf("%lld",&x);
	ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(ma[i]*mb[j]<=x)	ans=max((int)ans,i*j);
		}
	}
	printf("%lld",ans);
}

E题 CodeForces - 122D Lucky Transformation

题意:输入n,k,一长度为n的数字字符串。每次操作从左到右找到第一个"47",判断它的起始下标是奇数还是偶数,如果是奇数替换为"44",偶数替换为"77",最多可以操作k次。输出操作后的字符串。
思路:把"47"换为"44"只会对当前位置之后产生影响,而换为"77"会对当前位置之前产生影响。若遍历到第i位,此时i为偶数,“Si-1,Si,Si+1”=“447”,则这部分会产生"447"->“477”->“447”->…的循环,此时判断剩余操作数奇偶性即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
int n,k,len;
char s[100010];
int main(){
	scanf("%d %d",&n,&k);
	scanf("%s",s);
	len=strlen(s);
	for(int i=0;i<len-1;i++){
		if(k==0)	break;
		if(s[i]=='4'&&s[i+1]=='7'){
			if(i>0&&s[i-1]=='4'){
				if(i%2){
					if(k%2)	s[i]='7';
					k=0;continue;
				}
			}
			if(i%2)	s[i]='7';
			else	s[i+1]='4';
			k--;
		}
	}
	printf("%s",s);
}
儒略是从公元前 4713 年 1 月 1 正午 12 点到此后某一时刻间所经过的天,不满一天者用小表达,利用它可方便计算时间差值[^1]。对于儒略相关题目,如 csp - s2020 儒略,解题思路与方法如下: ### 理解题目要求 明确题目是根据输入的儒略 $r_i$,输出对应的期字符串 $s_i$,并清楚公元后和公元前的输出格式差异。例如,公元后格式为 “Day Month Year”,公元前格式为 “Day Month Year BC”,且、月、年均不含前导零,中间用空格隔开[^2]。 ### 分析历法规则 需要了解儒略历和格里高利历的规则,包括平年、闰年的判断方法以及每个月的天。在儒略历中,每四年一闰;在格里高利历中,年份能被 4 整除但不能被 100 整除的为闰年,此外能被 400 整除的也是闰年。同时,不同月份的天有所不同,1、3、5、7、8、10、12 月有 31 天,4、6、9、11 月有 30 天,2 月平年 28 天,闰年 29 天。 ### 实现步骤 1. **确定年份范围**:根据儒略的起始时间和输入的儒略值,逐步推算年份。可以先计算出大致的年份范围,再根据历法规则精确确定具体年份。 2. **确定月份和期**:在确定年份后,根据该年是平年还是闰年,计算每个月的天,从 1 月开始依次减去每个月的天,直到剩余天小于当前月的天,此时确定月份和期。 ### 代码示例(Python 伪代码) ```python def julian_day_to_date(r_i): # 公元前 4713 年 1 月 1 开始 year = -4713 # 先处理年份 while True: if is_leap_year(year): days_in_year = 366 else: days_in_year = 365 if r_i < days_in_year: break r_i -= days_in_year year += 1 # 处理月份和期 months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if is_leap_year(year): months[1] = 29 month = 1 while r_i >= months[month - 1]: r_i -= months[month - 1] month += 1 day = r_i + 1 # 处理输出格式 if year < 0: return f"{day} {month} {-year} BC" else: return f"{day} {month} {year}" def is_leap_year(year): # 判断闰年的函 if year < 0: # 公元前闰年规则 return (abs(year) - 1) % 4 == 0 elif year < 1582: # 儒略历闰年规则 return year % 4 == 0 else: # 格里高利历闰年规则 return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) # 示例调用 r_i = 10000 # 假设输入的儒略 date_str = julian_day_to_date(r_i) print(date_str) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值