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 <= T <= 20
- 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;
}