Блог пользователя Nadim

Автор Nadim, 2 года назад, По-английски

Given an array of N positive integers a = {a1, a2, a3,......, an},
Find a pair of integers (ai, aj) such that gcd(ai, aj) = 1

Constraints:

  • 2 <= N <= 105
  • 1 <= ai <= 106
  • Проголосовать: нравится
  • +24
  • Проголосовать: не нравится

»
2 года назад, # |
Rev. 3   Проголосовать: нравится +8 Проголосовать: не нравится

correct me if i am wrong but can't this be solved using sieve? you can count number of multiples of k that is presented in your array where 1 < k <= 1e6 then whenever you find that you have number of multiple of k less than n and greater than or equal 1 all you need to is taking any number that is multiple of k with any number that isn't multiple of k time complexity O(klogk)

  • »
    »
    2 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Okay.This only make sure that those 2 numbers won't have k as a common divisor. But it is possible that they have other divisors common, making gcd > 1. We need to make sure they don't have any divisor common. Say a = {x=2*5, y=3*5}. If you set k=2, then still gcd(x,y) = 5

»
2 года назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

https://codeforces.net/contest/548/problem/E Here is a similar problem we can use inclusion and exclusion for this one and simple formula Nc2 we can solve this in o(n) * 2^7 7 is the max number of unique primes for any number lessthan 1e6 we can do it using bitmaks 01 bick the prime or leave it or we can use backtracking for the same idea Or we can solve it in o(n) * the number of divisors for each element search about that

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

what i think here is

we have to make a smallest prime factor for each no and store them now we create some hashset which contains the no of smallest prime factor divisor now we know that the no of pair of frequency of all the smallest individual prime no and we just calculate the all pair using some mathmetical calculations and the ans is [total pair] — [total pair which gcd >1] for example 2 4 6 8 3 9 so the point is

number-> smallest prime factor

2 -> 2

4 -> 2

6 -> 2

8 -> 2

3 -> 3

9 -> 3 so roughly we have 2's -> 4 time and 3-s -> 2 time

sorry i am bit lazy please complete this on your own :)

  • »
    »
    2 года назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    The number of pairs having gcd = 1 can be found using sieve of eratosthenes. Problem is to find some index i and j for which gcd(ai, aj) = 1

»
2 года назад, # |
Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится

Please refer to this formula.

We just change the floor value of N/d to the multiple of d. We apply the sieve of Eratosthenes to find the number of multiple of d. My implementation is below. I hope it will help you.

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> P;
const static int maxn=1000002;
signed Eu[maxn];
bool vis[maxn];
int cnt[maxn];
signed prim[maxn];
signed minPrim[maxn];
signed top = 0;
void init_Prime()
{
	vis[0] = vis[1] = 1;
	for (int i = 2; i < maxn; i++)
	{
		if (!vis[i])prim[top++] = i;
		for (int j = 0; j < top&&i*prim[j] < maxn; j++)
		{
			vis[i*prim[j]] = 1;
			minPrim[i*prim[j]] = prim[j];
			if (i%prim[j] == 0)break;
		}
	}
}

signed mobs[maxn];
void mobius()
{
	signed cnt = 0;
	init_Prime();
	for (int i = 2; i < maxn; i++)
	{
		signed tmp_i = i;
		signed tmp_tmp_i;
		cnt = 0;
		signed miu = 1;
		while (vis[tmp_i] && tmp_i != 1)
		{
			tmp_tmp_i = tmp_i;
			cnt = 0;
			while (tmp_i%minPrim[tmp_tmp_i] == 0)
				tmp_i /= minPrim[tmp_tmp_i],cnt++;
			if (cnt == 1)miu *= -1;
			else if (cnt >= 2)miu *= 0;
		}
		if (tmp_i != 1)
		{
			miu *= -1;
		}
		mobs[i] = miu;
	}
	mobs[1] = 1;
	
}
int arr[maxn];

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	long long t, n, m, A, B,d, C, D,u,v,k,x,y,z;
	string str;
    mobius();
    cin>>t;
    //t=10;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>A,cnt[A]++;
//In this part, we use the sieve of Eratosthenes to find the number of d's multiple which is represented as cnt[d]
        for(int i=1;i<=1000000;i++){
            for(int j=2*i;j<=1000000;j+=i)
                cnt[i]+=cnt[j];
        }
        int ans = 0;
        for (int i = 1; i <= 1000000; i++)
            ans += mobs[i] * cnt[i]*cnt[i];//the floor of N/d and M/d is changed to the multiple of d
        cout << ans<< endl;
        
        memset(cnt,0,sizeof cnt);
    }
	return 0;
}
  • »
    »
    2 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    I assume your code returns the number of such pairs for which gcd = 1, but the problem is to find some index i and j for which gcd(ai, aj) = 1

    • »
      »
      »
      2 года назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      the result of my code is the pair of (i j),which satisfys that gcd(ai,aj)=1.Please refer to my input section. You can also run this code to verify my words

      • »
        »
        »
        »
        2 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Your code printing only the "ans" variable which you are printing in line 78

    • »
      »
      »
      2 года назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      You can run binary search for the first prefix of $$$a$$$ such that the count of pairs with gcd equal to 1 is greater than 0. Let it be $$$i$$$. Then just iterate over all $$$j < i$$$ and check if $$$(j, i)$$$ works.

  • »
    »
    2 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    what is $$$\mu(d)$$$ here?

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Check if any of them is 1, if found, then yes
Else, count the multiples of ai in the array, the count should be n if there is no j, such that gcd(ai, aj) = 1

Overall, you can solve this in AlogA, where A is 1e6

  • »
    »
    2 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    I guess this is necessary, but not sufficient. However, the problem requires explicitly the indices i, j for which gcd(ai, aj) = 1

    • »
      »
      »
      2 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Maybe if you sort it it can work?

      • »
        »
        »
        »
        2 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Don't think so. If you have an idea please elaborate a little more

        • »
          »
          »
          »
          »
          2 года назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          I was thinking that if you find some element that isn't a multiple of the smallest value, it may be coprime with the smallest value. Otherwise they all have a common divisor

    • »
      »
      »
      2 года назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      I think the condition is sufficient, if you have any edge case, let me know. Also, to find the pair of indices, you can just break at the index (let's say i) for which count < n, and then check for every index j, for which gcd(ai, aj) = 1

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Hey! Do you have an opportunity to submit a solution for this task? If it's possible for everyone, could you share the link please?

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

I think that you can just sort your array in increasing order. After that you iterate over all i And you should check every j, such that i — 20 <= j < i. I think that is enough because the product of the smallest 20 primes is bigger than 1e6

»
2 года назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

Look up Möbius inversion

»
2 года назад, # |
Rev. 3   Проголосовать: нравится +8 Проголосовать: не нравится

For each $$$x\le 10^6$$$, count how many multiples of $$$x$$$ there are in the array, and store this value in $$$\textrm{cnt}[x]$$$.

For each element $$$a_i = p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m}$$$ in the array, the number of elements in the array coprime to $$$a_i$$$ can be calculated by the inclusion-exclusion principle which gives the formula

$$$N - (\textrm{cnt}[p_1] + \cdots + \textrm{cnt}[p_m]) + (\textrm{cnt}[p_1p_2] + \cdots + \textrm{cnt}[p_{m-1}p_m]) -\cdots$$$
$$$=\sum_{i=0}^m(-1)^i\sum_{\textrm{sym}}cnt[p_1\cdots p_i]$$$
$$$=\sum_{d\vert a_i}\mu{(d)}\textrm{cnt}[d]$$$

Now for each array element we check if this value is non-zero, and if it is, we break and use another loop to find the corresponding element.

  • »
    »
    2 года назад, # ^ |
    Rev. 2   Проголосовать: нравится +4 Проголосовать: не нравится
    Code btw
    • »
      »
      »
      2 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Thanks. One thing I want to ask. How did you convert that inclusion-exclusion equation into something of mobius function?

      • »
        »
        »
        »
        2 года назад, # ^ |
        Rev. 5   Проголосовать: нравится +1 Проголосовать: не нравится

        That's kinda how mobius function is defined actually

        According to Wikipedia,

        • $$$\mu(n)=+1$$$ if $$$n$$$ is a square-free positive integer with an even number of prime factors.

        • $$$\mu(n)=-1$$$ if $$$n$$$ is a square-free positive integer with an odd number of prime factors.

        • $$$\mu(n)=0$$$ if $$$n$$$ has a squared prime factor.

        (Square-free means the integer isn't divisible by any square of a prime.)

        So basically summing over the divisors $$$d$$$ of a number $$$n=p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m}$$$ looks like

        $$$\sum_{d\vert n}\mu(d)f(d) $$$

        $$$= 1 - (f(p_1) + \cdots + f(p_m)) + (f(p_1p_2) + \cdots + f(p_{m-1}p_m)) - \cdots + (-1)^mf(p_1p_2\cdots p_m)$$$

        Because all the terms where a prime has a power greater than one will have a coefficient of $$$\mu(d)=0$$$

      • »
        »
        »
        »
        2 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        I highly recommend reading these CP tutorials as well: zhtluo.com

  • »
    »
    2 года назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    I think dropping prime powers gives a better complexity here

    • »
      »
      »
      2 года назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      Lol i literally just came here to post about it when i realized and then I saw your comment

      This should work right?
»
2 года назад, # |
  Проголосовать: нравится +10 Проголосовать: не нравится

Iterate from 0..i until we get gcd(a0,a1,...,ai)=1, then can we say that there is an element at j from 0..i — 1 that gcd(aj,ai) == 1?

»
2 года назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится

https://ideone.com/cOvEqC here is my solution, its complexity is O(n * 2^p) where p is at most 8. there is a corner case that can be handled easily which is when the gcd of all the array is greater than 1

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Initial idea, might be wrong. Lets count gcd of our array from the start. At some index, lets call it $$$i$$$, it will turn to 1, that means that gcd of $$$a[i]$$$ and some element in $$$a[:i]$$$ equals one. Factorize $$$a[i]$$$ and for every its factor mark elements on our prefix that are divisible by it. In the end, we will have some unmarked indexes — take any of them.

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

find index for which prefix gcd equals to 1 and that will absolutely 1 of the number. then iterate over all the array and find another number which is coprime to the number at that index.

»
2 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

If we only want to find one such pair of ai, aj than we can divide it into two part :

base case if 1 is in the array just print it with any number

Part — 1 : Lets focus on finding one of the elements in the array a, such that the no. of elements that have gcd != 1 with it are < n — 1 , we can find it using the inclusion exclusion,

Part — 2 : we alreadty know one ai that gives me the solution than I can just iterate over entire array and find aj such that gcd(ai, aj) = 1