zzulioj - 2623: 小H的作业题(素数筛选,打表)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2623

  看到这题第一眼想到的打表,首先筛选出来1e6之内的素数,然后我们再对1e6之内的数求其每个素因子的最高幂次有没有是偶数的情况,当然这样直接做的话肯定会超时的,所以我们要优化一下,在这个数除以某个素因子之后,他肯定是比原来小的,由于我们是顺序打表,所以比这个数小的数的情况我们已经判断过了,所以直接利用就行了。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define mst(a) memset(a, 0, sizeof(a))
#define _test printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const double eps = 1e-7;
const int INF = 0x3f3f3f3f;
const ll ll_INF = 0x3f3f3f3f3f3f3f;
const int maxn = 1e6+10;
int prime[maxn];
bool ok[maxn];
void solve1() { //筛素数
    fill(prime, prime+maxn, 1);
    prime[0] = prime[1] = 0;
    int end = sqrt(maxn) + 0.5;
    for (int i = 2; i<=end; ++i)
        if (prime[i])
            for (int j = i*2; j<maxn; j+=i)
                prime[j] = 0;
}
bool solve2(int n) {
    int t = n;
    if (prime[t]) //显然素数不行
        return false;
    for (int i = 2; i<t && n != 1; ++i) {
        int cnt = 0;
        if (prime[i]) { //计算素因子最高幂次
            while(!(n%i)) {
                n /= i;
                ++cnt;
            }
        }
        if ((!(cnt%2) && cnt)) //如果某个素因子最高幂次是偶数,那么符合要求
            return true;
        else if (n < t)
            return ok[n]; //n<t的情况我们已经算出来了,所以我们直接返回就是了
    }
    return false; 
}
int main(void) {
    solve1();
    for (int i = 1; i < maxn; ++i) //打表,方便下面O(1)查找
        ok[i] = solve2(i);
    int t;
    scanf("%d", &t);
    while(t--) {
        int n;
        scanf("%d", &n);
        printf(ok[n] ? "YES\n" : "NO\n");
    }
    return 0;
}

 

posted @ 2019-12-21 23:49  shuitiangong  阅读(309)  评论(0编辑  收藏  举报