有关此问题的详细信息,请查看此处:https://www.interviewstreet.com/challenges/dashboard/#problem/4f7272a8b9d15
有一个友好号码和N个不友好号码。我们想知道有多少数字与友方数字完全分开,但不会划分任何不友好的数字。
输入格式: 第一行输入包含由空格分隔的两个数字N和K. N是不友好号码的数量,K是友好号码。 第二行输入包含N个空格分隔的不友好数字。
输出格式: 将答案输出一行。
约束:
1 <= N <= 10^6
1 <= K <= 10^13
1 <= unfriendly numbers <= 10^18
示例输入:
8 16
2 5 7 4 3 8 3 18
示例输出:
1
说明: 给定友方号码16的除数是{1,2,4,8,16},而不友好的数字是{2,5,7,4,3,8,3,18}。现在1划分所有不友好的数字,2划分2,划分4,8划分8但是16划分他们。所以只有一个数字可以划分友方数字,但不会划分任何不友好的数字。所以答案是1.
很多人都问过这个问题,但没有给出完美答案。这不是重复,因为其他人关闭,我得问这个问题
我使用了Eratosthenes的Sieve来改进不友好的数字(删除重复数据,删除不必要的数字,如2和4中给出的例子。除以2和4的数字也除以8,所以只有8个wud用于此目的。完成所有这些后,我删除了素数)
这是我的代码
import java.io.*;
import java.util.*;
public class unfriendly {
public static ArrayList<Long> refine_unfriendly(ArrayList<Long> uf){
int n=uf.size();
long x;
for(int i=uf.size()-1;i>=0;i--){
x=uf.get(i);
for(int j=uf.size()-1;j>=0;j--){
if(j==i)
continue;
if(j!=i && uf.get(j)%x==0){
x=uf.get(j);
uf.remove(i);
break;
}
else if(j!=i && x%uf.get(j)==0){
uf.remove(j);
break;
}
}
}
return uf;
}
public static void print_output(long k,ArrayList<Long> uf){
int n=uf.size(),count=0,i;
long x,y;
if(n==0)
count++;
for(x=2;x<=Math.sqrt(k);x++){
if(k%x==0){
for(i=0;i<n;i++){
if(uf.get(i)%x==0)
break;
}
if(i==n)
count++;
if(k/x!=x){
y=k/x;
for(i=0;i<n;i++){
if(uf.get(i)%y==0)
break;
}
if(i==n)
count++;
}
}
}
for(i=0;i<n;i++){
if(uf.get(i)%k==0)
break;
}
if(i==n)
count++;
System.out.println(count);
}
public static void main(String[] args) throws Exception {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
long k=in.nextLong();
ArrayList<Long> uf=new ArrayList<Long>();
for(int i=0;i<n;i++)
uf.add(in.nextLong());
uf=refine_unfriendly(uf);
print_output(k,uf);
}
}
这解决了6个中只有1个测试用例。休息超过了时间限制。蛮力方法(无精炼)解决了3个测试案例。有人请帮忙。
提前致谢
答案 0 :(得分:3)
你只生成K的所有除数(它需要sqrt(K)时间),并且你创建了一个新的唯一GCD数组(a [i],K),因为如果友方数的除数除了不友好的数字那么它必须划分GCD(不友好的数字,K),所以你只需使用set,因为GCD(a [i],K)有nd(K)数,其中nd(K)代表K的除数数。因此算法只需要O(nd(K)^ 2)时间。
Here is main body of my code :
for(int i=1;i<=n;i++)
mm.insert(gcd(a[i],k));
vv=(int)sqrt((double)k);
for(int i=1;i<=vv;i++)
{
if(k%i==0)
{
zz[++cur]=i;
zz[++cur]=k/i;
}
}
if((ll)vv*(ll)vv==k)
cur--;
int say=0;
for(int i=1;i<=cur;i++)
{
q=0;
for(it=mm.begin();it!=mm.end();it++)
if(*it%zz[i]==0)
{
q=1;
break;
}
if(q==0)
say++;
}
cout<<say<<endl;
答案 1 :(得分:2)
首先,在F中生成K的所有因子。这可以在O(√K)时间内天真地完成。
对于每个不友好的数字Ui,计算gcd(K,Ui)并将其存储在集合S中。对于N个坏数字需要O(NlogK)。
最后,我们通过在F中找出因子中无因子数的因子来计算答案。因为两组最多包含| F |。数字,那么这需要O(| F | ^ 2)时间。
答案 2 :(得分:1)
你的提炼
for(int i=uf.size()-1;i>=0;i--){
x=uf.get(i);
for(int j=uf.size()-1;j>=0;j--){
是不友好数字N
的二次方。由于N
可能大到10 6 ,这可能是非常慢的操作。
对于小N
,无论如何检查不友好号码的完整列表很快,对于大N
,精炼过于昂贵。结论:放弃炼油,这是一个坏主意。
比检查sqrt(k)
之前的每个数字更快,是否划分k
,如果是,它是否划分任何不友好的数字是首先获得{{1的除数列表从它的素因子化(除非k
是素数或两个接近素数的乘积,然后两种方式同样快)。如果k
有多个除数(虽然要考虑的除数列表仍然很大),您可以通过计算k
和g
的最大公约数k
来排除其中的许多除数。不友好的号码,从列表中删除g
的所有除数。一旦列表变得足够短,就进行简单的成对检查
for u in unfriendlyNumbers
for d in divisors
if u%d == 0
remove d from divisors
成为更好的选择。
答案 3 :(得分:0)
你可以使用GCD获得不友好号码和友方号码k之间的所有常见除数。 O(N)
然后得到K,O(sqrt(K))的所有除数。
然后使用O(N * sqrt(K))的两个内部循环得到res :)。享受;)
答案 4 :(得分:0)
正在运行的代码却让我得分低,可能是因为findFactorsOfNumber方法的时间复杂度更高:
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Solution {
private Long n, k;
private static long result = 0;
private Set<Long> unfriendlyNumbers;
private Solution() {
this.unfriendlyNumbers = new HashSet<Long>();
}
public static void main(String[] args) {
Solution solution = new Solution();
Scanner scanner = new Scanner(System.in);
solution.n = scanner.nextLong();
solution.k = scanner.nextLong();
for (long l = 0; l < solution.n; l++) {
solution.unfriendlyNumbers.add(scanner.nextLong());
}
Set<Long> factors = findFactorsOfNumber(solution.k);
// find gcd of k and each of n unfriendly numbers
Set<Long> gcdSet = new HashSet<Long>();
for (long unfriendlyNumber : solution.unfriendlyNumbers) {
gcdSet.add(gcd(solution.k, unfriendlyNumber));
}
// check for those factors which are not the factors for any number in gcdSet
result = factors.size();
for (Long factor : factors) {
for (long gcd : gcdSet) {
if ((gcd >= factor && gcd % factor == 0)) {
result--;
break;
}
}
}
System.out.println(result);
}
private static Set<Long> findFactorsOfNumber(Long input) {
long increment = 1;
if (input % 2 != 0) {
increment = 2;
}
Set<Long> list = new HashSet<Long>();
for (long i = 1; i <= input / 2; i = i + increment) {
if (input % i == 0) {
list.add(i);
}
}
list.add(input);
return list;
}
public static long gcd(long p, long q) {
if (q == 0) {
return p;
}
return gcd(q, p % q);
}
}