2018 CCPC Guilin Station G.最大公約数(gcd微分素因数分解)

トピックリンク:最大公約数

一般的なアイデア

nnの長さが与えられた任意の数の操作を実行できるnのシーケンス:すべての位置の値に+1

Q:少なくともgcd({a 1、a 2、。。。。、a})≠1 gcd(\ {a_1、a_2、...、a_n \})\ne1となるように実行される操作の数g c d { a1a2an} =1.解決策がない場合は、-1-1を出力します−1 _

問題解決のアイデア

差分

このタイプの間隔を追加して、gcdgcdを見つけますg c dの問題については、それを差に変換して解決するというアイデアを簡単に考えることができます

この問題の場合、毎回、間隔[1、n] + 1 [1、n]+1を作成します。[ 1 n ]+1.元のシーケンスが[]a[]のa [ ]、差分シーケンスはb []b[]です。b [ ] 。この操作は、 b [1] + 1、b [n + 1] − 1 b [1] + 1、b [n +1]-1を作成するのと同じです。b [ 1 ]+1 b [ n+1 ]1. n+ 1 n+1n+1位置操作は無意味であるため、操作は次のようになりますb[1] + 1

ここで問題となるのは、少なくともgcd({b 1、b 2、。。。。、bn})≠1 gcd(\ {b_1、b_2、...、b_n \})\neb[1] + 1となるような操作がいくつ実行されるかです。 1g c d { b1b2bn} =1

簡単に次のようになります。ifgcd({b 2、b 3、。。。。、bn})= 1 gcd(\ {b_2、b_3、...、b_n \})= 1g c d { b2b3bn} =1の場合、解決策はありません


素因数分解

逆に、d = gcd({b 2、b 3、。。。。、bn})d = gcd(\ {b_2、b_3、...、b_n \})とします。d=g c d { b2b3bn} 。同等に、 gcd(b 1、d)≠1 gcd(b_1、d)\ne1を見つける必要があります。g c d b1d =1の最小操作数

b1b_1にする必要がありますb1およびdddが同じ素因数の少なくとも1つを持っていれば十分です。

したがってd素因数に分解され、すべての結果を列挙することにより、最小値を取ります

ACコード

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E5 + 10;
int a[N], b[N];
int get(int d) {
    
     return (d - b[1] % d) % d; }
int fact(int d) {
    
    
	int res = INT_MAX;
	for (int i = 2; i <= d / i; ++i) {
    
    
        if (d % i == 0) {
    
    
            res = min(res, get(i));
            while (d % i == 0) d /= i;
        }
    }
    if (d > 1) res = min(res, get(d));
	return res;
}
int main()
{
    
    
	int t; cin >> t;
	rep(tt, t) {
    
    
		int n; scanf("%d", &n);
		rep(i, n) scanf("%d", &a[i]), b[i] = abs(a[i] - a[i - 1]);

		int d = 0;
		for (int i = 2; i <= n; ++i) d = gcd(d, b[i]);

		if (d == 0) printf("Case %d: %d\n", tt, b[1] == 1);
		else {
    
    
			int res = fact(d);
			printf("Case %d: %d\n", tt, res == INT_MAX ? -1 : res);
		}
	}

	return 0;
}

終わり

おすすめ

転載: blog.csdn.net/weixin_45799835/article/details/122667714