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 .
这个题直接去求gcd显然并不现实。
在这里学习的一个比较巧妙的方法就是倒着来,我们选定i之后,对于两个区间的数分别找出来以i为约数的所有的数的个数num[i]。
对于序列A和序列B分别记为numa[i]和numb[i[。
之后numa[i]*numb[i]表示的是什么呢,自然是以i为最大公约数或者以i的倍数为最大公约数的所有数对的和。
然后我们再减去以i的倍数为最大公约数的数对个数,最后剩下的就是自然是以i为最大公约数的数对的总数了。
这样复杂度就能降低很多了,使n变成一个logn。
方法确实巧妙,倒着来想,我自己想的话估计要想好久。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,q;
const int MAXN=1e5+7;
const int mod=1e9+7;
int a[MAXN],b[MAXN];
long long numa[MAXN],numb[MAXN];
long long ans[MAXN];
int main()
{
int i,j;
scanf("%d%d%d",&n,&m,&q);
for(i=0;i<n;++i)scanf("%d",&a[i]);
for(i=0;i<m;++i)scanf("%d",&b[i]);
int l1,r1,l2,r2;
while(q--)
{
memset(numa,0,sizeof(numa));
memset(numb,0,sizeof(numb));
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
for(i=l1;i<=l2;++i)numa[a[i]]++;
for(i=r1;i<=r2;++i)numb[b[i]]++;
for(i=1;i<=100000;++i)
{
for(j=i*2;j<=100000;j+=i)
{
numa[i]+=numa[j];
numb[i]+=numb[j];
}
}
int cnt=0;
for(i=100000;i>=1;--i)
{
ans[i]=numa[i]*numb[i];
for(j=i*2;j<=100000;j+=i)
{
ans[i]-=ans[j];
}
if(ans[i])cnt++;
}
printf("%d\n",cnt);
}
}