CF1547F. Array Stabilization (GCD version) *

46 篇文章 1 订阅
37 篇文章 0 订阅

Link
gcd 思维 1900

题意

给定一个长度为n的数组, 下标从1~n. 其中an和a1相连(成环).
每轮操作得到一个新的数组b: 对于所有的i∈[1, n], b[i] = gcd(a[i], a[i + 1]) (b[n] = gcd(a[n], a[1])). 最后把新数组b复制给原数组a.
问: 执行完多少轮操作后, a数组中的所有数字都相同.

思路

x x x 轮操作后, b 1 = g c d ( a 1 , a 2 , . . . , a x ) b_1 = gcd(a_1,a_2,...,a_x) b1=gcd(a1,a2,...,ax),所以最多 n n n 轮就会全部相等,考虑二分。对于每一个二分值 m i d mid mid, 若对 i ∈ [ 1 , n ] , g c d ( i , i + m i d ) i \in [1, n],gcd(i, i + mid) i[1,n]gcd(i,i+mid) 均相等,则满足条件。此外,由于是环状,只要长度*2倍即可。

代码

int d[maxn][30];
int n;
int a[maxn];
int gcd (int a, int b) {
	if(!b) return a;
	return gcd(b, a % b);
}
void init() {
	for(int i = 1; i <= n; i++) d[i][0] = a[i];
	for(int j = 1; (1 << j) <= n; j++) {
		for(int i = 1; i +(1 << j) - 1 <= n; i++) {
			d[i][j] = gcd(d[i][j-1], d[i+(1<<(j-1))][j-1]);
		}
	}
}
int query(int l, int r) {
	int len = r - l + 1;
	int k = 0;
	while((1<<(k + 1)) <= len) k++;
	return gcd(d[l][k], d[r - (1 << k) + 1][k]);
}
bool ok(int x) {
	int ans = query(1, 1 + x);
	for(int i = 2; i <= (n/2); i++) {
		if(query(i, i + x) != ans) return false;
	}
	return true;
}
void solve() {
    cin >> n;
    // for(int i = 1; i <= 2 * n; i++)
    
    for(int i = 1; i <= n; i++) {
    	cin >> a[i];
    	a[i + n] = a[i];
    }
    int l = 0, r = n;
	int res = n;
    n <<= 1;
    init();
    while(l <= r) {
    	int mid = (l + r) >> 1;
    	if(ok(mid)) {
    		res = mid;
    		r = mid - 1;
    	}
    	else l = mid + 1;
    }
    cout << res << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值