没啥时间写,所以写的比较草率。
而且不知道为什么最近发博客的 LaTeX \LaTeX LATEX 都渲染成很丑的样子了,CSDN 能不能修一下啊?
T1
题目大意
不好描述
代码
不太需要
T2
题目大意
求一个长度为 n n n 的序列中的最大连续子段和。
数据范围
忘了,但是开到 n ⩽ 1 0 5 n\leqslant 10^5 n⩽105 绰绰有余。
题解
一眼 DP,不细说了,属于是真的没啥好讲的:
d p i = max ( d p i − 1 + a i ) dp_{i}=\max(dp_{i-1}+a_i) dpi=max(dpi−1+ai)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int dp[N],a[N],ans=0,n;
int main(){
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i]=max(0,a[i]);
for(register int i=1;i<=n;i++){
dp[i]=max(dp[i-1]+a[i],dp[i]);
}
for(register int i=1;i<=n;i++) ans=max(ans,dp[i]);
printf("%d",ans);
}
T3
题目大意
有无限个 1 1 1 分, 2 2 2 分, 5 5 5 分, 10 10 10 分的硬币,你需要适当的组合他们,使得恰好取到 n n n 分钱,问有多少种本质不同的方案。
题解
因为本质不同了,所以交换两个硬币的顺序是没意义的,显然不能直接递推过去。
所以完全背包 DP 一下,由于物品只有四个,你可以拆成四个循环,反正就是先取若干 1 1 1 分钱,再取若干 2 2 2 分钱,以此类推。时间复杂度 O ( n ) \mathcal{O}(n) O(n)。
非常需要注意的点
脑抽把完全背包写成多重背包了。
为什么 d p i = d p i − 1 + d p i − 2 + d p i − 5 + d p i − 10 dp_{i}=dp_{i-1}+dp_{i-2}+dp_{i-5}+dp_{i-10} dpi=dpi−1+dpi−2+dpi−5+dpi−10 是错的?注意到在这个状态转移方程下, d p 11 dp_{11} dp11 可能从 d p 10 dp_{10} dp10 推导过来,相当于先选择了一个 10 10 10 分硬币,再选择了一个 1 1 1 分硬币。而根据题目意思,硬币顺序不同,但是本质是相同的,所以这种解法已经被 d p 1 dp_1 dp1 重复计算了一遍,导致答案错误。
那为什么拆开这个循环,四次循环是对的,因为我限定他必须先选 1 1 1 分,再选 10 10 10 分,不可能会存在 d p 11 dp_{11} dp11 从 d p 10 dp_{10} dp10 推导过来导致重复计算的情况。这也是背包 DP 最核心的基础,强制要求一堆物品要按顺序选择。而这题明显是完全背包 DP 的模型,所以其本质的状态转移方程是:
d p i , j = d p i − 1 , j − 1 / 2 / 5 / 10 + 1 dp_{i,j}=dp_{i-1,j-1/2/5/10}+1 dpi,j=dpi−1,j−1/2/5/10+1
而由于我们通常会对 01 背包和完全背包 DP 进行滚动数组优化,所以我们省去了 i i i 的那一维,此时如果打的是 01 背包 DP,则需要将循环倒过来,防止一种物品被重复选择,但是完全背包 DP 就不用倒过来循环,因为本来就可以选择多次。
为了防止某些人误导萌新特意贴出来的一部分。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int N=1e5+5;
int dp[N],n;
int main(){
scanf("%d",&n);
dp[1]=1;
for(register int i=1;i<=n;i++){
if(i>=1) dp[i]=(dp[i]+dp[i-1])%mod;
}
dp[2]++;
for(register int i=1;i<=n;i++){
if(i>=2) dp[i]=(dp[i]+dp[i-2])%mod;
}
dp[5]++;
for(register int i=1;i<=n;i++){
if(i>=5) dp[i]=(dp[i]+dp[i-5])%mod;
}
dp[10]++;
for(register int i=1;i<=n;i++){
if(i>=10) dp[i]=(dp[i]+dp[i-10])%mod;
}
printf("%d",dp[n]);
}
T4
题目大意
不好描述,但是原题戳这 → \to → CF148B。
题解
不太需要,他说啥你做啥。稍微特判一下就行。
代码
#include<bits/stdc++.h>
using namespace std;
double vp,vd,t,f,c;
int main(){
scanf("%lf %lf %lf %lf %lf",&vp,&vd,&t,&f,&c);
if(vp>=vd){
printf("0");
return 0;
}
int ans=0;
double now=vp*t;
while(1){
double res=now*1.0/(vd-vp);
now+=vp*res;
if(now-c>=0){
printf("%d",ans);
return 0;
}
now+=(res+f)*vp;
ans++;
}
printf("%d",ans);
}