https://www.hackerrank.com/contests/hourrank-17/challenges/gcd-matrix
Alex has two arrays defined as and . He created an matrix, , where for each in . Recall that is the greatest common divisor of and .
For example, if and , he builds like so:
Alex's friend Kiara loves matrices, so he gives her questions about matrix where each question is in the form of some submatrix of with its upper-left corner at and its bottom-right corner at . For each question, find and print the number of distinct integers in the given submatrix on a new line.
Input Format
The first line contains three space-separated integers describing the respective values of (the size of array ), (the size of array ), and (Alex's number of questions).
The second line contains space-separated integers describing .
The third line contains space-separated integers describing .
Each line of the subsequent lines contains four space-separated integers describing the respective values of , , , and for the question (i.e., defining a submatrix with upper-left corner and bottom-right corner ).
Constraints
Scoring
- for of score.
- for of score.
Output Format
For each of Alex's questions, print the number of distinct integers in the given submatrix on a new line.
Sample Input 0
3 3 3
1 2 3
2 4 6
0 0 1 1
0 0 2 2
1 1 2 2
Sample Output 0
2
3
3
Explanation 0
Given and , we build the following :
The diagram below depicts the submatrices for each of the questions in green:
- For the submatrix between and , the set of integers is . The number of distinct integers is .
- For the submatrix between and , the set of integers is . The number of distinct integers is .
- For the submatrix between and , the set of integers is . The number of distinct integers is .
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
long long A[111111],B[111111];
long long sa[111111],sb[111111];
long long num[111111];
int main()
{
int n,m,q;
int x,y,s,e;
scanf("%d%d%d",&n,&m,&q);
for(int i=0;i<n;i++)scanf("%lld",&A[i]);
for(int j=0;j<m;j++)scanf("%lld",&B[j]);
while(q--)
{
scanf("%d%d%d%d",&x,&y,&s,&e);
memset(sa,0,sizeof(sa));
memset(sb,0,sizeof(sb));
for(int i=x;i<=s;i++)sa[A[i]]++;///在A中以A[i]为约数的个数,即A[i]本身
for(int j=y;j<=e;j++)sb[B[j]]++;///在B中以B[j]为约数的个数,即B[j]本身
for(int i=1;i<=100000;i++)
{
for(int j=i*2;j<=100000;j+=i)
{
sa[i]+=sa[j];///以i的倍数为约数的一定可以约掉i,即i是该数的约数
sb[i]+=sb[j];///同理
}
}
int ans=0;
memset(num,0,sizeof(num));
for(int i=100000;i>=1;i--)///倒序求的原因:在求以i为最大公约数的时候,要减去以i的倍数为最大公约数的个数
///i的倍数是比i的大的数中的,那么如果正序的话,在求完小的后,后面的num值都减去了,无法求后面以大数为公约数时的值了
///而且因为在矩阵中的约数都是最简化的了,所以先求后面的,把大数都减去后剩下的必然是最大公约的了
{
num[i]=sa[i]*sb[i];///以i为约数的的个数相乘,即以i或i的倍数为最大公约数的对数,可以免去用矩阵的左上角和右下角去求
for(int j=i*2;j<=100000;j+=i)
{
num[i]-=num[j];
}
if(num[i])ans++;
}
printf("%d\n",ans);
}
return 0;
}