gcd-matrix

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:

image

  1. For the submatrix between  and , the set of integers is . The number of distinct integers is .
  2. For the submatrix between  and , the set of integers is . The number of distinct integers is .
  3. 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较简单的数学题,可以用矩阵快速幂求解。以下是 C++ 代码实现: ```c++ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int MAXN = 2; const int MOD = 1e9 + 7; struct Matrix { LL m[MAXN][MAXN]; Matrix() { memset(m, 0, sizeof(m)); } Matrix operator * (const Matrix& b) const { Matrix c; for (int i = 0; i < MAXN; ++i) { for (int j = 0; j < MAXN; ++j) { for (int k = 0; k < MAXN; ++k) { c.m[i][j] = (c.m[i][j] + m[i][k] * b.m[k][j]) % MOD; } } } return c; } } base, res; Matrix qpow(Matrix a, int b) { Matrix ans; for (int i = 0; i < MAXN; ++i) { ans.m[i][i] = 1; } while (b) { if (b & 1) { ans = ans * a; } a = a * a; b >>= 1; } return ans; } LL gcd(LL a, LL b) { return b == 0 ? a : gcd(b, a % b); } int main() { LL a, b, n; cin >> a >> b >> n; if (n == 1) { cout << a << endl; } else if (n == 2) { cout << b << endl; } else { base.m[0][0] = base.m[0][1] = base.m[1][0] = 1; res = qpow(base, n - 2); LL ans = gcd(a * res.m[0][0] % MOD + b * res.m[1][0] % MOD, b * res.m[1][0] % MOD + b * res.m[1][1] % MOD); cout << ans << endl; } return 0; } ``` 在这段代码中,我们定义了一个 `Matrix` 结构体,它表示一个 $2\times2$ 的矩阵。其中重载了 `*` 运算符,实现了矩阵乘法。 然后,我们定义了一个矩阵快速幂函数 `qpow`,用于求解矩阵的 $n$ 次方。 最后,在 `main` 函数中,我们通过快速幂求出矩阵 $base$ 的 $n-2$ 次方,然后根据题目要求求出 $\gcd(F_N, F_{N+1})$ 并输出即可。 需要注意的是,当 $n=1$ 或 $n=2$ 时,直接输出 $a$ 或 $b$ 即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值