ABC288 EFG 题解
E
注意到后面选对前面的答案没有影响,而且前面选的顺序对后面的影响是连续的一段(如选 2 个,那么对应的 就应该是 (对应 是 1、2、3 个选时的答案))
然后就可以 dp 了:设 表示考虑到前 个物品,选了 个时的最小花费,转移分两种情况:
- 选了第 个:
- 没选(注意此时该物品不能在愿望单上)
答案就是
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 2e5+5;
int n,k,a[maxn],c[maxn],must[maxn];
ll dp[5005][5005];
signed main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&c[i]);
for(int i=1,x;i<=k;i++){
scanf("%d",&x);
must[x] = 1;
}
for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)dp[i][j] = 1e18;
dp[0][0] = 0;
for(int i=1;i<=n;i++){
ll cst = 1e18;
if(!must[i])dp[i][0] = dp[i-1][0];
for(int j=1;j<=i;j++){
cst = min(cst, 1ll * c[i - j + 1]);
dp[i][j] = min(dp[i][j], dp[i-1][j-1] + cst + a[i]);
if(!must[i])dp[i][j] = min(dp[i][j], dp[i-1][j]);
}
}
ll ans = 1e18;
for(int i=k;i<=n;i++)ans = min(ans, dp[n][i]);
cout << ans << '\n';
return 0;
}
F
设 表示考虑到第 位时的所有情况之和
然而直接转移是 的,需要优化
考虑将 拆开
代入,
发现拆开之后恰好能用 表示,即
每次转移的时候维护一下 dp 的前缀和即可
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, mod = 998244353;
int n;
char s[200005];
ll dp,sdp;
signed main(){
scanf("%d",&n);
scanf("%s",s +1);
dp = s[1] - '0';sdp = dp+1; // +1(dp[0]=1)
for(int i=2;i<=n;i++){
int c = s[i]-'0';
dp = (dp*10%mod + sdp*c%mod) % mod;
(sdp += dp) %= mod;
}
cout << dp << '\n';
return 0;
}
G
注意到如果将三进制每一位拆开,题目中给的条件实际上相当于是一系列和
第 位为 0,说明至少有 个数,这一位为 0,1 (加起来)
为 1,说明这一位为 0,1,2
为 2,则为 1,2
因此相当于是做一个高级的差分,具体细节等之后再补充一下
UPD:
现在相当于告诉你的 是每一位符合 1,2,3 条件的 的前缀和,要求一个 ,相当于 是 的高维前缀和(注意这里不是二进制而是三进制)
做法就是
枚举一下三进制位,每次在某一位为 0 的时候更新差分数组
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 1e6+5;
int n,p3[15],a[maxn];
signed main(){
scanf("%d",&n);
p3[0] = 1;
for(int i=1;i<=n;i++)p3[i] = 3*p3[i-1];
for(int i=0;i<p3[n];i++)scanf("%d",&a[i]);
for(int i=0;i<n;i++){
for(int j=0;j<p3[n];j++)if((j/p3[i])%3 == 0){
int v0=j, v1=j+p3[i], v2=j+2*p3[i];
int w0=a[v0], w1 = a[v1], w2 = a[v2];
a[v2]=w1-w0; a[v0]=w1-w2; a[v1]=w1-a[v2]-a[v0];
}
}
for(int i=0;i<p3[n];i++)printf("%d ",a[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示