CF1593D1题解

CF1593D1题解

题意

把题意转换一下就可以得到:给定一个数列 a1,a2,a3,,an,要求一个数列 bb 中的数为非负整数)和一个正整数 k,使得 a[1]b[1]×k=a[2]b[2]×k==a[n]b[n]×k。若有无数多个 k,请输出 1。(有多组数据)

思路

首先直接讲解法:将数组去重并判断是否有无数多个 k 之后再两两作差求最大公因数即可。那么就有以下解释:

  1. 咋去重?答:建立一个 vis 数组和 a 数组,vis 数组为判断一个数是否已经出现过,a 数组为去重之后的数组,如果一个数没有出现过,就录入到数组 a 中。
  2. 咋判断有无数多个 k?答:在去重的时候,用一个 len 记录去重之后的数组长度,如果为 1,也就是去重以前所有数都相同,所以 k 为任意数,输出 1
  3. 为啥用两两相减求最大公因数?接下来我就来证明。

证明:

aibi×k=ajbj×k

aiaj=k×(bibj)

aiaj(modk)

a1a2a3an(modk)

只要两两作差求最大公因数即可。

总结

  1. 多组数据。
  2. 换行。
  3. 两两作差求最大公因数。
  4. 去重。
  5. 特判。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int T;
int n,a[45],ans,cnt,len;
bool vis[2000005];
//a数组为去重之后的数组 
//cnt为临时变量。
//len为去重之后的数组长度。
//vis数组是一个数字是否出现过的统计数组,去重要用。 
int gcd(int a, int b){//求最大公因数 
	if(b==0) return a;
	return gcd(b,a%b);
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		memset(vis,0,sizeof(vis));//一定要重置。 
		len=0;
		for(int i=1; i<=n; i++){
			scanf("%d",&cnt);
			if(vis[cnt+1000001]==0){//以前这个数没出现过(这个数是新的)。 
				vis[cnt+1000001]=1;//标记为出现过(旧的)。 
				a[++len]=cnt;//录入a数组 
			}
		}
		if(len==1){//去重之后只有1个数,也就是去重以前所有数都相同,所以k为任意数,输出-1。 
			printf("-1\n");//别忘了换行 
			continue;
		} 
		ans=abs(a[2]-a[1]);//取绝对值
		for(int i=2; i<len; i++)
			for(int j=i+1; j<=len; j++)
				ans=gcd(ans,abs(a[j]-a[i]));
		printf("%d\n",ans);
	}
	return 0;
} 

附(选看)

怎么求最大公因数

方法 1:用唯一分解定理,先分解质因数,然后求最大公因数。

a=pa11×pa22×pa33×pammb=pb11×pb22×pb33×pbmm

gcd(a,b)=pmin(a1,b1)1×pmin(a2,b2)2×pmin(a2,b2)2×pmin(am,bm)m

方法 2:九章算术 更相减损术。

a,bNba,有 gcd(a,b)=gcd(b,ab)=gcd(a,ab)

a,bN,有 gcd(2a,2b)=2gcd(a,b)

证明:

对于 ab 的任意公约数 d,因为 d|ad|b,所以 d|(ab)。因此,db(ab) 的公约数。反之亦成立。

方法 3:欧几里得算法。

a,bNb0gcd(a,b)=gcd(b,amodb)

证明:

a<b,则 gcd(b,amodb)=gcd(a,b),命题成立。

ab,设 a=q×b+r,其中 0r<b。显然 r=amodb。对于 ab 的任意公约数 d,因为 d|ad|q×b,所以 d|(aqb)。即 d|r,因此,dbr 的公约数。反之亦成立。所以他们的最大公因数相等。

代码实现:

int gcd(int a, int b){ 
	if(b==0) return a;
	return gcd(b,a%b);
}
posted @   naroto2022  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
不相信人咬不到肚脐的,咬破肚脐去死如何?