您的位置:首页 > 其它

gcd-matrix

2017-02-10 20:04 281 查看
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 .

题目大意:有两个序列A和B,用这两个序列组成一个矩阵M(i,j)=gcd(A[i],B[j]),给出左上角和右下角的坐标,求这块区域中不同的数有多少个

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: