HDU3826 Squarefree number【Eratosthenes筛选法+欧拉筛+唯一分解定理】

Squarefree number

Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4271 Accepted Submission(s): 1149

Problem Description
In mathematics, a squarefree number is one which is divisible by no perfect squares, except 1. For example, 10 is square-free but 18 is not, as it is divisible by 9 = 3^2. Now you need to determine whether an integer is squarefree or not.

Input
The first line contains an integer T indicating the number of test cases.
For each test case, there is a single line contains an integer N.

Technical Specification

  1. 1 <= T <= 20
  2. 2 <= N <= 10^18

Output
For each test case, output the case number first. Then output “Yes” if N is squarefree, “No” otherwise.

Sample Input
2
30
75

Sample Output
Case 1: Yes
Case 2: No

Author
hanshuai

Source
The 6th Central China Invitational Programming Contest and 9th Wuhan University Programming Contest Final

问题链接HDU3826 Squarefree number
问题简述:给定一个n,如果可以被一个平方数整除,则不是平方自由数,输出No,否则输出Yes。
问题分析
    这个问题的n比较大,n<=1018,使用筛选法是不可能筛选出那么多素数来。
    解决这个问题,需要了解数论的唯一分解定理。考虑x=106,那么xxx<=n,如果存在素数y>x,其平方数能够整除n,那么n必然存在因子n/(yy)<x,也就是说不可能出现y的3及其以上的次方能够整除n的情况,因为yy*y>n。算法的思路是先筛选出所有<=106的所有素数,用这些素数迭代除n(n越来越小),进行判定。若用所有的这些素数迭代除n后满足n>106,那么再进行开方乘方判定一下即可。
程序说明:(略)
参考链接:(略)
题记:(略)

AC的C++语言程序(欧拉筛)如下:

/* HDU3826 Squarefree number */

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e6;
bool isprime[N + 1];
int prime[N / 3], pcnt = 0;
// 欧拉筛
void eulersieve(void)
{
    memset(isprime, true, sizeof(isprime));

    isprime[0] = isprime[1] = false;
    for(int i = 2; i <= N; i++) {
        if(isprime[i])
            prime[pcnt++] = i;
        for(int j = 0; j < pcnt && i * prime[j] <= N; j++) {  //筛选
            isprime[i * prime[j]] = false;
            if(i % prime[j] == 0) break;
        }
    }
 }

LL n;

bool judge()
{
    for(int i = 0; n && i < pcnt; i++) // n为0时,就不必试除
        if(n % prime[i] == 0) {
            n /= prime[i];
            if(n % prime[i] == 0) return true;
        }
    return false;
}

int main()
{
    eulersieve();

    int t, caseno = 0;

    scanf("%d", &t);
    while(t--) {
        scanf("%lld", &n);

        bool flag = judge();
        if(n > N) {
            LL t = sqrt(n);
            if(n == t * t) flag = true;
        }

        printf((flag ? "Case %d: No\n" : "Case %d: Yes\n"), ++caseno);
    }

    return 0;
}

AC的C++语言程序(Eratosthenes筛选法)如下:

/* HDU3826 Squarefree number */

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e6;
const int SQRTN = sqrt((double) N);
bool isprime[N + 1];
int prime[N / 3], pcnt = 0;
// Eratosthenes筛选法
void esieve(void)
{
    memset(isprime, true, sizeof(isprime));

    isprime[0] = isprime[1] = false;
    for(int i = 2; i <= SQRTN; i++)
        if(isprime[i]) {
            prime[pcnt++] = i;
            for(int j = i * i; j <= N; j += i)  //筛选
                isprime[j] = false;
        }

    for(int i = SQRTN + 1; i <= N; i++)
        if(isprime[i])
            prime[pcnt++] = i;
 }

LL n;

bool judge()
{
    for(int i = 0; n && i < pcnt; i++) // n为0时,就不必试除
        if(n % prime[i] == 0) {
            n /= prime[i];
            if(n % prime[i] == 0) return true;
        }
    return false;
}

int main()
{
    esieve();

    int t, caseno = 0;

    scanf("%d", &t);
    while(t--) {
        scanf("%lld", &n);

        bool flag = judge();
        if(n > N) {
            LL t = sqrt(n);
            if(n == t * t) flag = true;
        }

        printf((flag ? "Case %d: No\n" : "Case %d: Yes\n"), ++caseno);
    }

    return 0;
}
发布了2126 篇原创文章 · 获赞 2306 · 访问量 254万+

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/104521879