首页 > 其他分享 >【题解】ARC153 A-D

【题解】ARC153 A-D

时间:2023-02-14 17:44:19浏览次数:37  
标签:res int 题解 d% pos 进位 ARC153 dp

怎么感觉 ARC 困难的永远是 B 题[惊恐]

A.AABCDDEFE

题目分析:

完全可以把相等的位置合并在一起,这样就剩下了 \(6\) 个位置,然后就转化为了第 \(N\) 小的六位数是多少,这应该没人不会吧。

代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int a[10];
int main(){
	int s;scanf("%d",&s);
	s--;
	for(int i=6; i>=1; i--){
		a[i] = s % 10 + (i == 1);
		s /= 10;
	}
	printf("%d%d%d%d%d%d%d%d%d",a[1],a[1],a[2],a[3],a[4],a[4],a[5],a[6],a[5]);
	return 0;
}

B.Grid Rotations

题目分析:

可以发现我们的 \(x\) 和 \(y\) 坐标的翻转是互不影响的,所以就可以分开计算。
(然后傻逼的我就没有发现分开后就是区间翻转,然后直接平衡树就好了)
这个时候也没啥办法了,就硬推呗。
假设我们的给定点为 \((a,b)\),当前考虑的点为 \((x,y)\),考虑其 \(x\) 坐标经过翻转后变成了什么。
这个时候显然需要分类讨论了:

\[\begin{aligned} &x \to a - x & x \le a\\ &x \to a - x + n & x > a\\ \end{aligned} \]

这其实就是 \(a-x\) 在模 \(n\) 意义下的值,所以就根据这个把多次操作合并一下就好了。
具体来说就是不管 \(x\) 只记录多次操作会让前面的 \(a\) 变成什么,然后根据奇偶性判断一下 \(x\) 取正还是负就好了。

代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
int posx[N],posy[N],x[N],y[N];
vector<char> v[N];
char s[N];
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int n,m;scanf("%d%d",&n,&m);
	for(int i=0; i<n; i++){
		scanf("%s",s+1);
		for(int j=1; j<=m; j++)	v[i].push_back(s[j]);
	}
	int q,dx = 0,dy = 0;
	scanf("%d",&q);
	for(int i=1; i<=q; i++){
		scanf("%d%d",&x[i],&y[i]);x[i]--;y[i]--;
	}
	for(int i=q; i>=1; i--){
		dx = x[i] - dx;
		dy = y[i] - dy;
	}
	if(q & 1){
		for(int i=0; i<n; i++)	posx[i] = ((dx - i)%n + n)%n;
		for(int i=0; i<m; i++)	posy[i] = ((dy - i)%m + m)%m;
	}
	else{
		for(int i=0; i<n; i++)	posx[i] = ((dx + i)%n + n)%n;
		for(int i=0; i<m; i++)	posy[i] = ((dy + i)%m + m)%m;
	}
	for(int i=0; i<n; i++){
		for(int j=0; j<m; j++){
			printf("%c",v[posx[i]][posy[j]]);
		}
		printf("\n");
	}
	return 0;
}

C.Increasing Sequence

题目分析:

看到要求严格单调递增,直觉肯定是先构造出一个 \([0,n-1]\)。
然后其实发现这个条件完全可以去调整,比如说对于一段区间,其 \(1\) 的个数为 \(x\) 而 \(-1\) 的个数为 \(y\),那么将区间全部加 \(1\) 造成的贡献就是 \(x-y\)。
为了使得严格单调递增的条件成立,那么就是要前缀减或者后缀加,就很简单了。
我们最好是选择一个 \(1\) 和 \(-1\) 的个数相差为 \(1\) 的区间,因为这样区间加的值很好计算。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+5;
int a[N],x[N],ans;
bool flag= false;
signed main(){
	int n;scanf("%lld",&n);
	for(int i=1; i<=n; i++)	scanf("%lld",&a[i]);
	for(int i=1; i<=n; i++)	x[i] = i-1,ans += x[i] * a[i];
	//后缀加--------------------------------------------------------- 
	int res = 0,pos = n+1;
	if(ans > 0){
		for(int i=n; i>=1; i--){
			res+=a[i];
			if(res < 0)	{   //草,压行真压出事了 
				pos = i;break;
			}
		}
		if(pos != n + 1)	flag = true;
		for(int i=pos; i<=n; i++)	x[i] += ans;
	}
	else if(ans < 0){
		for(int i=n; i>=1; i--){
			res += a[i];
			if(res > 0){
				pos = i;break;
			}
		}
		if(pos != n + 1)	flag = true;
		for(int i=pos; i<=n; i++)	x[i] += -ans;
	}
	else	flag = true;
	//前缀减--------------------------------------------------------- 
	if(!flag){  //前缀减
		pos = n + 1,res = 0; 
		if(ans > 0){
			for(int i=1; i<=n; i++){
				res+=a[i];
				if(res > 0)	{   //草,压行真压出事了 
					pos = i;break;
				}
			}
			if(pos != n + 1)	flag = true;
			for(int i=1; i<=pos; i++)	x[i] -= ans;
		}
		else if(ans < 0){
			for(int i=1; i<=n; i++){
				res += a[i];
				if(res < 0){
					pos = i;break;
				}
			}
			if(pos != n + 1)	flag = true;
			for(int i=1; i<=pos; i++)	x[i] -= -ans;
		}
		else	flag = true;
	}
	if(flag){
		printf("Yes\n");
		for(int i=1; i<=n; i++)	printf("%lld ",x[i]);
	}
	else	printf("No\n");
	return 0;
}

D.Sum of Sum of Digits

题目分析:

因为低位会对高位产生影响,所以我们显然需要从低到高考虑,这个题显然贪心不大对,所以就考虑 \(dp\)。
知道了上面这一条其实就很容易可以想到这样的一个 \(dp\) 状态:\(dp[i][j][0/1]\) 表示前 \(i\) 位,考虑了前 \(j\) 个数,其中第 \(j\) 个数当前位没有/有进位的最小的 \(f\) 的和。
推推转移的话会发现,仿佛根本推不出来啊,而且统计答案也显然很难做,那么就考虑一下是不是状态有啥问题。
第一维没啥说的了,看第二维和第三维,这个其实本质上是因为我们的转移肯定需要知道各个数的进位情况,但是我们并不需要以这种形式放到状态里啊,因为对于当前位会产生进位贡献的一定是按当前位从大到小排序后的一个前缀,所以其实直接记 \(dp[i][j]\) 表示前 \(i\) 位当前有 \(j\) 个进位的最小的 \(f\) 的和。
这样就很简单了,就是枚举一下这一位选什么,然后计算一下进位与进位的贡献就好了。如果是由于上一位的进位而产生的进位其实就是会对我们这一位的和产生一个 \(-9\) 的贡献。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+5;
const int INF = 1e9+5;
int res,a[N],pos[N],dp[11][N];
bool cmp(int x,int y){
	return a[x] % res > a[y] % res;
}
signed main(){
	int n;scanf("%lld",&n);
	for(int i=1; i<=n; i++)	scanf("%lld",&a[i]),pos[i] = i;
	memset(dp,0x3f,sizeof(dp));
	res = 1;dp[0][0] = 0;
	for(int i=1; i<=10; i++,res *= 10){
		sort(pos+1,pos+n+1,cmp);
		for(int j=0; j<=9; j++){
			int cnt = 0,sum = 0;
			for(int k=1; k<=n; k++)	cnt += ((a[k] / res)%10 + j) > 9,sum += ((a[k] / res)%10 + j)%10;
			dp[i][cnt] = min(dp[i][cnt],dp[i-1][0] + sum);
			for(int k=1; k<=n; k++){
				if((a[pos[k]] / res)%10 + j == 9)	cnt++,sum -= 9;
				else	sum++;
				dp[i][cnt] = min(dp[i][cnt],dp[i-1][k] + sum);
			}
		}
	}
	int ans = INF;
	for(int i=0; i<=n; i++)	ans = min(ans,dp[10][i] + i);
	printf("%lld\n",ans);
	return 0;
}

标签:res,int,题解,d%,pos,进位,ARC153,dp
From: https://www.cnblogs.com/linyihdfj/p/17120266.html

相关文章

  • Magic Powder - 1 题解
    更好的阅读体验1.题意题目大意就是一块曲奇饼干需要\(n\)种食材,第\(i\)种需要\(a_i\)克,而你手中有这种食材\(b_i\)克,还有另外\(k\)克食材每一克可以代替任何......
  • Magic Powder - 2 题解
    更好的阅读体验1.题意题目大意就是一块曲奇饼干需要\(n\)种食材,第\(i\)种需要\(a_i\)克,而你手中有这种食材\(b_i\)克,还有另外\(k\)克食材每一克可以代替任何......
  • Rescheduling the Exam 题解
    题意:题意简单明了,就不多赘述了。解题方法:这道题我们要考虑贪心。由于我们只有一次修改\(a_i\)的机会,所以我们修改的值一定是产生最小距离的两个相邻的点之中修改。那......
  • F1 Champions 题解
    题意已知\(n\)场比赛前\(m\)名的名字,每场比赛前\(10\)名各有不同的分数,求以下两种排名方法排名第一的人的名字。按照分数排序,若分数相同,第\(1\)次数多的优先,若......
  • Social Network 题解
    题意:题目翻译是有问题的,题目的真正意思其实是\(∀i∈[1,d]\),求在满足\([1,i]\)的规定的前提下恰好连\(i\)条边的无向图中度数最大联通块的大小减\(1\)。思路考虑......
  • P8827 [传智杯 #3 初赛] 森林 题解
    题意有一颗树,每个点有一个点权\(v\)。现在要对这棵树进行\(m\)次以下三种操作之一:删除一条边。修改一个点的点权。查询一个点\(u\)所在的树的点权之和。......
  • lg8365题解
    容易发现我们一定会先加后乘,使用调整法可以证明这个结论。并且可以发现除了\(a_i\)值为\(1\)的数外(假设他们的\(a\)值和为\(s\)),其他的数最多只会选\(1\)个做加法操作(设如......
  • Vue项目在ie浏览器中显示空白的兼容性问题解决
    问题:在ie浏览器中页面报错:SCRIPT5022:SecurityError小编也不知道原因是什么,小编是尝试了以下几种方式才显示出来,这里建议大家试试看。1、下载软件包:@babel/polyfill执......
  • elementUI的table表格改变数据不更新问题解决
    问题原因:在Vue实例创建时,以及data赋值时editable并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新。解决方案:1、给data赋值前把editable属......
  • C++奥赛一本通递推题解
    title:C++奥赛一本通刷题记录(递推)date:2017-11-08tags:一本通openjudegecategories:OIC++奥赛一本通刷题记录(递推)2017.11.8Bygwj1139177410斐波那契数列​​op......