CodeForces - 892C Pride

题意:给你一个长度为n的数组,每次可以进行一种操作把第i个数和第i+1个数替换为第i个数或者第i+1个数的gcd,问最少多少步能够使得序列全部变成1.

思路:这道题的只要数组里面有一个1 ,操作就变得简单了。如果只有一个1那么只要再执行n - 1步操作就可以全变成1,i个1就执行n-i步操作,就可以了,如果给的初始数组没有1那么我们就化出一个1来再加上n - 1,考虑每一段区间i ~ j(i < j)上的情况:记g(i,j)=gcd{a[i]|i=i,...,j},则有以下递推关系式:g( i , j + 1 ) = gcd( g ( i , j ) , a [ j + 1])。若存在i < j,使得g(i,j)=1,令d=j - i,则有操作步数为n+d-1。注意这个操作步数的计算。在当前情况下,首先在区间i ~ j上构造出一个元素1:d步;再用这个1与其他元素作gcd运算:n-1步。于是总操作步数为n+d-1。于是,枚举i , j,求最小的d=j - i。

AC代码:

#include<stdio.h>
#define INF 100000000
#define maxn 2005

int n;
int ans[maxn];

int gcd(int a, int b) {
	if (b == 0) {
		return a;
	}
	else {
		gcd(b, a % b);
	}
}

int main() {
	scanf("%d", &n);
	int t = 0;
	for(int i = 0; i < n; i++) {
		scanf("%d", &ans[i]);
		if (ans[i] == 1) {
			t++;
		}
	}
	if (t) {
		printf("%d\n", n - t);
	}
	else {
		int d = INF;
		for(int i = 0; i < n; i++) {
			int g = ans[i];
			for(int j = i + 1; j < n; j++) {
				g = gcd(g, ans[j]);
				if(g == 1 && j - i < d) {
					d = j - i;
				}
			}
		}
		if (d != INF) {
			printf("%d\n", n + d - 1);
		}
		else {
			printf("-1\n");
		}
	}
	return 0;
}

 

全部评论

相关推荐

不愿透露姓名的神秘牛友
2024-12-30 18:02
程序员牛肉:1.可以标记一下自己的学校是985,有一些hr可能没想到你这个院校是985的。 2.简历所呈现出来的能力还是有点差的,苍穹外卖+黑马点评。这在java技术域里面也就是刚学三四个月的样子,大厂现在招人少,小厂又更加希望你能直接过来干活。就你简历上呈现出来的能力,确实是有点难找,肉眼可见的不懂技术。 第一个项目中:简单的使用redis也算是亮点嘛?使用jwt,threadlocal也算是亮点?你不就是调了几个包嘛?Nginx作为服务器也能写出来,这不是前端的活嘛? 第二个项目中:分布式锁+mq消息队列+Lua队列。真没啥好问的。属于面试官看一眼就阳痿的简历,没有任何想提问的欲望。 我给你建议是好好的挖一挖这个项目吧,其实苍穹外卖和黑马点评这两个项目很不错了,只不过是太烂大街了导致面试官没啥问的兴趣,所以不太推荐写简历上。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务