牛客OI赛制测试赛2 A 无序组数

链接:https://www.nowcoder.com/acm/contest/185/A
来源:牛客网

题目描述

给出一个二元组(A,B)
求出无序二元组(a,b) 使得(a|A,b|B)的组数
无序意思就是(a,b)和(b,a) 算一组.

输入描述:

第一行数据组数 T(1≤T≤10000)
接下来T行,每行两个正整数 A,B(1≤A,B≤10000)

输出描述:

共T行,每行一个结果
示例1

输入

复制
1
4 6

输出

复制
11

说明

样例解释:
二元组如下:
(1,1)(1,2)(1,3)(1,6)
(2,1)(2,2)(2,3)(2,6)
(4,1)(4,2)(4,3)(4,6)
共12组.
无序二元组如下:

(1,1)(1,2)(1,3)(1,6)
(2,2)(2,3)(2,6)
(4,1)(4,2)(4,3)(4,6)
共11组



$n^2$的暴力应该无脑写吧,就不在此多说了,直接讲正解。
a和b$le$10000,我不知道在一个循环里,for(i=1 ->max(a,b)),然后判断i与a,b的大小这样来枚举a,b的因数可不可以过,$1000 imes 10000$说不定可以试试。
我们来说我比较安全的解法。
我们需要先找出A,B每个数的因子个数,当然我们需要枚举,假设我们在枚举找出A的一个a,那么A/a又何尝不是另一个因子,这样的话我们找到一个因子,因子数加2,当然这个数最大为

为$sqrt A imes sqrt A$,所以我们对于每个T最多枚举$ sqrt A + sqrt B$次,当然对于$sqrt A$是A 的因子这种$i = A/ i $的情况需要特殊判断一下,只能因字数加1.

对于A的每个因子,用一个数组标记一下,为了方便判断B的因子中有多少个与之相同的数的个数。

同样的方法,我们求出B的同时记录有多少个相同的因子。

下面来说找出相同的因子数的个数怎么用。

设A的因字数为:1 3 4 5

设B的因子数为:1 4 5 7

我们用A的因子来配B的因子:1(4种),3(4种),4(3种),5(2种)

我们发现若这个数不是公共因子,那么对于每个数情况个数都为B的因子数量,若为公共因子,第一次出现情况数为B的因字数,第二次出现为B的因字数-1,第三次-2...。

那么答案就可以计算为:A的因子的个数$ imes$B的因子的个数-1-2-...-(公共因子数-1)。

对于-1-2..这部分可以稍微优化一下,作用不是很大啦。

if(sumv%2==0)sumv=(sumv+1)*(sumv/2);
else sumv=(sumv+2)*(sumv/2)+1;    //sumv表示公共因子个数。

代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int T,a,b,suma,sumb,sumv;
bool vis[100006];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        suma=sumb=sumv=0;
        scanf("%d%d",&a,&b);
        int p=sqrt(a);
        int q=sqrt(b);
        for(int i=1; i<=p; i++)
        {
            if(a%i==0)
            {
                if(a/i==i)suma+=1,vis[i]=1;
                else suma+=2,vis[i]=vis[a/i]=1;
            }
        }

        for(int i=1; i<=q; i++)
        {
            if(b%i==0)
            {
                if(b/i==i)sumb+=1,sumv+=vis[i];
                else sumb+=2,sumv+=vis[i],sumv+=vis[b/i];
            }
        }
        sumv--;
        if(sumv%2==0)sumv=(sumv+1)*(sumv/2);
        else sumv=(sumv+2)*(sumv/2)+1;
        printf("%d
",suma*sumb-sumv);
    }
}
原文地址:https://www.cnblogs.com/rmy020718/p/9602460.html