找到每个 K 使得 arr[i]%K 等于每个 arr[i]
Find every K such that arr[i]%K is equal to for each arr[i]
我有一个 M 整数数组。我必须找到所有可能的整数 K(假设至少有 1 K)这样:
1) K > 1
2) arr[0]%K = arr[1]%K = arr[2]%K = ... = arr[M-1]%K
这个问题的最佳算法是什么?
首先,让我们检查给定值。
- 鉴于至少存在一个
K
,我们知道,例如数组arr
使得arr[0]=4; arr[1]=6; arr[2]=9
无效,因为没有模数给出每个相同的结果。
- 鉴于
K
> 1,我们知道数组的所有值不可能相同。但是,它们对于所有 K
. 都是相同的 modK
请记住 arr[i]%K
(对于满足 0=<i<M
的任何 i)不一定是正数。
提出的算法
代码尚未测试
在我看来,确定 K
值的最简单方法就是找出数组中每个值之间的差异。 (我将在 Java 中展示示例。)假设 arrDiff
包含每个值的差异,使得
arrDiff[0] = arr[0]-arr[1];
arrDiff[1] = arr[1] - arr[2];
...
arrDiff[M-1] = arr[M-1] - arr[0];
现在,查找 G = gcd(arrDiff[0],arrDiff[1],...,arrDiff[M-1]
以查找所有有效的 K
。您可以使用您想要的任何 gcd
方法,即 Euclidean Algorithm,以便 iteratively/recursively 找到
G
。您也可以忽略负面差异,因为 gcd
会给您正面的结果。
[All of G's factors]>1
(包括 G
本身)将是有效的 K
值。
穿行其中
我不打算证明(我会把它留给你),但让我们举个例子来说明清楚。
初始化一个例子arr
//Let's do an easy one with M=3
int arr[] = new int[3];
arr[0] = -7;
arr[1] = 9;
arr[2] = 25
创建差异数组
我将在这里展示一个稍微更有效的实现(感谢@RBarryYoung)。
int min = findSmallestNumber(arr); //Returns min value (may be negative)
//The array size is intended to not include the minimum, assuming we have no duplicates.
int arrDiff[] = new int[arr.length-1];
for(int num : arr){
if(num==min) continue;
arrDiff[num] = arr[num] - min;
}
对于上面的示例,这段代码应该在 arrDiff
中为我们提供 16,32
的值。请注意,使用此方法应该会在下一步的 gcd 计算中产生所有正值。
计算G = gcd
我不打算为您编写 gcd 方法,因为有很多实现;我假设你有一个方法 int gcd(int a, int b)
.
int g = gcd(arrDiff[0], arrDiff[1]);
for(int i = 2, i < arrDiff.length-1, i++){
g = gcd(g, arrDiff[i]);
}
//return g;
请注意,如果我们在数组中只有两个值,则不需要 gcd
用法——只需使用一个差值即可。
检查示例
对于我们的示例,您可以很容易地发现 gcd(-16,-16,32)=gcd(16,16,32)=16。因此 16 及其所有大于 1 的因子应该是答案。让我们至少检查 16 个。请注意,下面的“=”实际上应该是同余符号(三个竖条而不是两个)。
-7mod16 = 9mod16
9mod16 = 9mod16
25mod16 = 9mod16
您可以检查这是否也适用于因子 2,4,8
。 (对于所有这些因素,您应该得到 1mod8 => 1mod4 => 1mod2
。)
总结
如果您必须在代码中找到因子,您可能会对各种 factoring algorithms 中的一种感兴趣,以找到 G
大于 1 的所有因子。选择最优化的可能取决于你的数据。
因此,它实际上是您可能需要的算法的组合。可能有更快的方法来完成我上面向您展示的操作,但现在应该可以理解基本算法了。
#include <stdio.h>
int GCD(int a, int b) {
while(a!=b) {
if(a>b) a-=b; else b-=a;
}
return a;
}
int main()
{
int n; scanf("%d",&n);
int a[n],i,j;
for(i=0;i<n;i++) {
scanf("%d",&a[i]);
}
//finding minimum
int min=a[0]; for(i=0;i<n;i++) if(min>a[i]) min=a[i];
//finding differences and storing except minimum
int diff[n-1]; for(i=0,j=0;i<n;i++) if(a[i]!=min) diff[j++]=a[i]-min;
// if n is 2, we have only diff[1], otherwise we can follow algo
int g=(n==2)?diff[0]:GCD(diff[0],diff[1]); for(i=2;i<n-1;i++) g=GCD(g,diff[i]);
//finding divisors of the final gcd.
for(i=2;i<=g;i++) if(g%i==0)printf("%d ",i);
return 0;
}
这是我解决问题的代码
#include<bits/stdc++.h>
using namespace std;
void printEqualModNumbers (int arr[], int n)
{
sort(arr, arr + n);
int d = arr[n-1] - arr[0];
vector <int> v;
for (int i=2; i*i<=d; i++)
{
if (d%i == 0)
{
v.push_back(i);
if (i != d/i)
v.push_back(d/i);
}
}
for (int i=0; i<v.size(); i++)
{
int temp = arr[0]%v[i];
int j;
for (j=1; j<n; j++)
if (arr[j] % v[i] != temp)
break;
if (j == n)
cout << v[i] <<" ";
}
}
int main(){
int n;
cin >> n;
int arr[n];
for(int i = 0 ; i < n ; i++)
cin >> arr[i];
printEqualModNumbers(arr, n);
}
我有一个 M 整数数组。我必须找到所有可能的整数 K(假设至少有 1 K)这样:
1) K > 1
2) arr[0]%K = arr[1]%K = arr[2]%K = ... = arr[M-1]%K
这个问题的最佳算法是什么?
首先,让我们检查给定值。
- 鉴于至少存在一个
K
,我们知道,例如数组arr
使得arr[0]=4; arr[1]=6; arr[2]=9
无效,因为没有模数给出每个相同的结果。 - 鉴于
K
> 1,我们知道数组的所有值不可能相同。但是,它们对于所有K
. 都是相同的
modK
请记住 arr[i]%K
(对于满足 0=<i<M
的任何 i)不一定是正数。
提出的算法
代码尚未测试
在我看来,确定 K
值的最简单方法就是找出数组中每个值之间的差异。 (我将在 Java 中展示示例。)假设 arrDiff
包含每个值的差异,使得
arrDiff[0] = arr[0]-arr[1];
arrDiff[1] = arr[1] - arr[2];
...
arrDiff[M-1] = arr[M-1] - arr[0];
现在,查找 G = gcd(arrDiff[0],arrDiff[1],...,arrDiff[M-1]
以查找所有有效的 K
。您可以使用您想要的任何 gcd
方法,即 Euclidean Algorithm,以便 iteratively/recursively 找到
G
。您也可以忽略负面差异,因为 gcd
会给您正面的结果。
[All of G's factors]>1
(包括 G
本身)将是有效的 K
值。
穿行其中
我不打算证明(我会把它留给你),但让我们举个例子来说明清楚。
初始化一个例子arr
//Let's do an easy one with M=3
int arr[] = new int[3];
arr[0] = -7;
arr[1] = 9;
arr[2] = 25
创建差异数组
我将在这里展示一个稍微更有效的实现(感谢@RBarryYoung)。
int min = findSmallestNumber(arr); //Returns min value (may be negative)
//The array size is intended to not include the minimum, assuming we have no duplicates.
int arrDiff[] = new int[arr.length-1];
for(int num : arr){
if(num==min) continue;
arrDiff[num] = arr[num] - min;
}
对于上面的示例,这段代码应该在 arrDiff
中为我们提供 16,32
的值。请注意,使用此方法应该会在下一步的 gcd 计算中产生所有正值。
计算G = gcd
我不打算为您编写 gcd 方法,因为有很多实现;我假设你有一个方法 int gcd(int a, int b)
.
int g = gcd(arrDiff[0], arrDiff[1]);
for(int i = 2, i < arrDiff.length-1, i++){
g = gcd(g, arrDiff[i]);
}
//return g;
请注意,如果我们在数组中只有两个值,则不需要 gcd
用法——只需使用一个差值即可。
检查示例
对于我们的示例,您可以很容易地发现 gcd(-16,-16,32)=gcd(16,16,32)=16。因此 16 及其所有大于 1 的因子应该是答案。让我们至少检查 16 个。请注意,下面的“=”实际上应该是同余符号(三个竖条而不是两个)。
-7mod16 = 9mod16
9mod16 = 9mod16
25mod16 = 9mod16
您可以检查这是否也适用于因子 2,4,8
。 (对于所有这些因素,您应该得到 1mod8 => 1mod4 => 1mod2
。)
总结
如果您必须在代码中找到因子,您可能会对各种 factoring algorithms 中的一种感兴趣,以找到 G
大于 1 的所有因子。选择最优化的可能取决于你的数据。
因此,它实际上是您可能需要的算法的组合。可能有更快的方法来完成我上面向您展示的操作,但现在应该可以理解基本算法了。
#include <stdio.h>
int GCD(int a, int b) {
while(a!=b) {
if(a>b) a-=b; else b-=a;
}
return a;
}
int main()
{
int n; scanf("%d",&n);
int a[n],i,j;
for(i=0;i<n;i++) {
scanf("%d",&a[i]);
}
//finding minimum
int min=a[0]; for(i=0;i<n;i++) if(min>a[i]) min=a[i];
//finding differences and storing except minimum
int diff[n-1]; for(i=0,j=0;i<n;i++) if(a[i]!=min) diff[j++]=a[i]-min;
// if n is 2, we have only diff[1], otherwise we can follow algo
int g=(n==2)?diff[0]:GCD(diff[0],diff[1]); for(i=2;i<n-1;i++) g=GCD(g,diff[i]);
//finding divisors of the final gcd.
for(i=2;i<=g;i++) if(g%i==0)printf("%d ",i);
return 0;
}
这是我解决问题的代码
#include<bits/stdc++.h>
using namespace std;
void printEqualModNumbers (int arr[], int n)
{
sort(arr, arr + n);
int d = arr[n-1] - arr[0];
vector <int> v;
for (int i=2; i*i<=d; i++)
{
if (d%i == 0)
{
v.push_back(i);
if (i != d/i)
v.push_back(d/i);
}
}
for (int i=0; i<v.size(); i++)
{
int temp = arr[0]%v[i];
int j;
for (j=1; j<n; j++)
if (arr[j] % v[i] != temp)
break;
if (j == n)
cout << v[i] <<" ";
}
}
int main(){
int n;
cin >> n;
int arr[n];
for(int i = 0 ; i < n ; i++)
cin >> arr[i];
printEqualModNumbers(arr, n);
}