Hankson的趣味题--acwing(快速求一个数的所有约数)

题目:https://www.acwing.com/problem/content/202/可能需要报名课程才能做。

题意:给a,b,c,d四个数,范围是1–2e9,求x和a的最大公约数是b,x和c的最小公倍数是d,满足条件的x有多少个。首先输入一个n,代表n组数据,n的范围是1-2000

题解:这个题其实就找d的所有约数,然后枚举每一个约数就行,int范围内数量最大的约数是1600,所以枚举不多,难的是求d的所有约数,因为有2000的输入,如果直接暴力求根下n的复杂度,如果给1s时间复杂度是可以过的,但题目给的是0.3s,所以不能暴力求。
较快速度求所有约数:可以先把d的所有质因数求出来,然后dfs暴力搜一下质因数的所有方案,时间复杂度比暴力求快10倍,就可以过了。

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+10;
int prime[N+10],vis[N+10];
int cnt;
struct node     //记录所有的质因数
{
    int p,s;  //p记录质数,s记录个数
} a[20];     
int node_cnt;  //记录有多少中质数
int arr[2000];  //存约数
int tol;       //记录有多少个约数
void init(int n)   //线性筛打素数表
{
    cnt=0;
    vis[0]=vis[1]=1;
    for(int i=2; i<=n; i++)
    {
        if(vis[i]==0)prime[cnt++]=i;
        for(int j=0; prime[j]*i<=n; j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
void dfs(int u,int data)  //dfs暴力找所有素数匹配方案,求出约数个数
{
    if(u==node_cnt)  //u==node_cnt说明后面已经没有质数了,记录下这个时候的data,
    {
        arr[tol++]=data;
        return ;
    }
    for(int i=0; i<=a[u].s; i++)  //从0开始循环个数
    { 
        dfs(u+1,data); //i=0的时候代表这个素数没有×
        data=data*a[u].p; //放在下边,i=1的时候,data正好乘素数一次
    }
    return ;
}
int main()
{
    init(N-9);
    int aa,b,c,d;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&aa,&b,&c,&d);
        node_cnt=0,tol=0;  //每次清空
        int t=d;
        for(int i=0; prime[i]*prime[i]<=d&&i<cnt; i++)  //分解质因数
        {
            int s=0;
            int p=prime[i];
            while(d%p==0)
            {
                s++;
                d=d/p;
            }
            if(s>0)
            {
                a[node_cnt].p=p;
                a[node_cnt++].s=s;
            }
        }
        if(d>1)  //如果还有保留,说明剩下的这个质数很大,也要加入
        {
            a[node_cnt++]= {d,1};
        }
        dfs(0,1);  //暴力搜索方案
        int sum=0;
        for(int i=0; i<tol; i++)  //遍历每一个约数
        {
            int data=arr[i];
            if(__gcd(data,aa)==b&&((ll)c*data)/__gcd(c,data)==t)sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

  

上一篇:javascript – 防止YUI中的键监听器中的默认行为


下一篇:2022-1-2 390. 消除游戏(找规律)