HDU 4320 Arcane Numbers 1(质因子)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4320

 

题意:
给你任意一个 p 进制下有限位数的数 n,问是否一定能转化成 q 进制下有限位数的数字 m。
解题思路:
显然若 n 为整数,一定可以,那么我们下面分析一下 n 含小数的情况。
设 n 的小数部分为 x,且小数部分共 k 位,第 i 位上的数字为 ai。
那么我们可以将 x 表示成下面式子的形式:

而在进制转化中,整数部分是“除基倒取余”,小数部分是“乘基正取整”,且乘到小数部分为0时截止。
于是问题转化成了 x 在什么时候小数部分“乘基”一定会变成0。
由 x 的表达式我们可知,当且仅当乘数中含有 p^k 这个因子时,x 的小数部分才为0。
那么就相当于判断 q^h 中是否含有 p^k 这个因子(h 可无限大)。
又由算术基本定理,p^k 中的质因子一定和 p 中的相同。
所以只要 q 中包含 p 的所有质因子,就必定存在 h 使得 q^h 中包含 p^k 这个因子,从而使问题有解。


那么,如何判断 q 中是否包含 p 的所有质因子呢?

 

朴素方法:

将素数存入prime数组中,然后从a的质因数出发,判断b mod (该质因数) == 0 ?

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

int visit[1000006],prime[400006];

void GetPrime(){

 int cnt=0;

 memset(visit,0,sizeof(visit));

 for(int i=2;i<1000006;i++){

  if(!visit[i]){

   prime[cnt++]=i;

  }

  for(int j=0;(j<cnt)&&(i*prime[j]<1000006);j++){

   visit[i*prime[j]]=1;

   if(i%prime[j]==0){

    break;

   }

  }

 }

}

int main(){

 int t,cases=1;

 scanf("%d",&t);

 GetPrime();           //素数表

 while(t--){

  __int64 a,b;

  scanf("%I64d %I64d",&a,&b);

  int flag=1;

  for(int i=0;prime[i]<=(int)sqrt(a)&&prime[i];i++){

   int x=prime[i];

   if(a%x==0){

    if(b%x!=0){

     flag=0;

     break;

    }

    while(a%x==0){

     a/=x;

    }

   }

  }

  if(a!=1&&b%a!=0){

    flag=0; 

  }

  printf("Case #%d: ",cases++);

  printf(flag? "YES\n":"NO\n");

 }

}

 

巧妙方法:

1、若 p 和 q 不互质,则只需要判断 q 中是否包含 p/gcd(p,q) 的所有质因子。
2、若 p 和 q 互质,当且仅当 p = 1 时,q 中包含 p 的所有质因子。

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <stack>

#include <queue>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>

#define MID(x,y) ((x+y)>>1)



using namespace std;

typedef __int64 LL;



LL gcd(LL a, LL b)

{

    return b?gcd(b,a%b):a;

}



bool fuck(LL A, LL B)     //判断B是不是包含A的所有质因子

{

    if (gcd(A, B)==1)

    {

        if (A==1)   return true;

        else return false;

    }

    else

        return fuck(A/gcd(A, B), B);

}



int main()

{

    //freopen("test.in","r+",stdin);



    int t, caseo = 1;

    scanf("%d",&t);

    while(t--)

    {

        printf("Case #%d: ", caseo ++);

        LL a,b;

        scanf("%I64d%I64d",&a,&b);

        if (fuck(a, b))

            printf("YES\n");

        else printf("NO\n");

    }

    return 0;

}

 

 

你可能感兴趣的:(number)