首页 > 其他分享 >ABC288 EFG 题解

ABC288 EFG 题解

时间:2023-02-06 12:56:20浏览次数:58  
标签:typedef .. int 题解 long ABC288 define dp EFG

E
注意到后面选对前面的答案没有影响,而且前面选的顺序对后面的影响是连续的一段(如选 2 个,那么对应的 \(c\) 就应该是 \(c[i-2..i]\)(对应 \(i\) 是 1、2、3 个选时的答案))
然后就可以 dp 了:设 \(dp[i][j]\) 表示考虑到前 \(i\) 个物品,选了 \(j\) 个时的最小花费,转移分两种情况:

  • 选了第 \(i\) 个:\(dp[i][j] \leftarrow dp[i-1][j-1]+a[i]+min{c[i-j+1], .., c[i]}\)
  • 没选(注意此时该物品不能在愿望单上) \(dp[i][j] \leftarrow dp[i-1][j]\)
    答案就是 \(min{dp[n][k..n]}\)
// 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[i]\) 表示考虑到第 \(i\) 位时的所有情况之和
\(dp[i] = \sum_{j=0}^{i-1}dp[j]\times x[j+1..i]\)
然而直接转移是 \(O(n^2)\) 的,需要优化
考虑将 \(x[j+1..i]\) 拆开 \(\rightarrow 10x[j+1..i-1] + x[i..i]\)
代入,\(dp[i] = \sum_{j=0}^{i-2}dp[j]\times 10x[j+1..i-1] + x[i..i]\sum_{j=0}^{i-1}dp[j]\)
发现拆开之后恰好能用 \(dp[i-1]\) 表示,即 \(dp[i] = 10dp[i-1] + x[i..i]\sum_{j=0}^{i-1}dp[j]\)
每次转移的时候维护一下 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
注意到如果将三进制每一位拆开,题目中给的条件实际上相当于是一系列和
\(a[x]\) 第 \(i\) 位为 0,说明至少有 \(a[x]\) 个数,这一位为 0,1 (加起来)
为 1,说明这一位为 0,1,2
为 2,则为 1,2
因此相当于是做一个高级的差分,具体细节等之后再补充一下

// 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;
}

标签:typedef,..,int,题解,long,ABC288,define,dp,EFG
From: https://www.cnblogs.com/SkyRainWind/p/17095068.html

相关文章

  • P3215 [HNOI2011]括号修复题解
    发现题解里的维护前后缀最大最小值的做法都是感性理解,所以我就来写个证明。将(看做\(-1\),)看做\(1\),首先几个变量:\(n\)代表括号序列的长度。\(a_i\)代表前缀和......
  • abc288
    C:如果当前连的边和以前连的形成了环,就任意删除一条边,并查集维护。E:首先需要知道,若考虑购买当前物品\(i\),那么设之前买了\(j\)个了,那么可以在\(c_{i-j+1}\simc_i......
  • CF884D 题解
    题目传送门题目分析开始还真没看出来这题跟\(\text{P1090}\)合并果子的关系。其实只要逆向思考,把拆分看成效果一样的合并就可以了。而与合并果子不同的是,在这题当中......
  • abc285h题解
    考虑容斥,强制要求\(k\)个数为完全平方数,系数为\((-1)^k*C_n^k\)(因为我们要从\(n\)个数选出\(k\)个数作为完全平方数)。则在唯一分解\(p_1^{e_1}...p_n^{e_n}\)中,\(e_1...e_n......
  • "_OBJC_CLASS_$ [文件名1]referenced from in[文件名2]:ld: symbol(s) not found问题
    说实话开发一年多了,遇到了至少三次以上这种问题,很困惑,也很难搞觉得,其实很简单解决办法,在buildPhases中添加文件名1的.m文件即可了。"_OBJC_CLASS_$"PackageTourCustomAnnot......
  • 【题解】20230204解题报告
    解题报告20230204主要学习内容有:动态规划,字符串操作(在另外一篇文章里)T1:P5322[BJOI2019]排兵布阵首先题意是设定有n座城堡,s个玩家(不包括特殊玩家),此时每名玩家都有m......
  • lg9035题解
    考虑枚举\(a_{n-1}=l\),根据题意\(l\leqa_n\leqk+1-l\),这说明\(a_n\)有\(k+1-2l\)种取值。令\(b_i=a_i-a_{i-1}\),则\(b_1\geq1\),\(b_i\geq0(i>1)\),\(b_1+...+b_{n-1}=l......
  • 洛谷P9035 Pont des souvenirs 题解
    题面很简洁,这里不做多说。70pts做法首先考虑到\(a_{n-1}\)和\(a_n\)两项是整个数列\(a\)中的最大的两项,所以若\(a_{n-1}+a_n\)不超过\(k+1\),则数列中任意两项......
  • P2016题解
    P2016题解题目描述Bob要建立一个古城堡,城堡中的路形成一棵无根树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能瞭望到所有的路。注意,某个士兵在一个结点上时......
  • CF1666K Kingdom Partition 题解
    神仙网络流题。Description传送门Solution考虑最小割,将每个点\(u\)拆成\(L_u,R_u\)两个点。对于每一条原图中的边\((u,v,w)\),连双向边\((L_u,R_v,w),(L_v,R_u,w)......