백준문제풀이

백준 문제 1016번 제곱 ㄴㄴ 수 문제풀이 c++

노가다 김씨 2022. 3. 22. 15:02

https://www.acmicpc.net/problem/1016

 

1016번: 제곱 ㄴㄴ 수

어떤 정수 X가 1보다 큰 제곱수로 나누어 떨어지지 않을 때, 그 수를 제곱ㄴㄴ수라고 한다. 제곱수는 정수의 제곱이다. min과 max가 주어지면, min보다 크거나 같고, max보다 작거나 같은 제곱ㄴㄴ수

www.acmicpc.net

 

문제해석

 

수의 범위가 굉장히 큰 것에 비해 max와 min의 차이는 최대 100만까지 나지 않는 점을 주목해야한다.

따라서 사실상 최대 100만 정도 배열이면 이 문제를 푸는데 지장이 없다.

 

min부터 max까지 순서대로 배열에 저장하고 이에 대해 에라토스테네스의 체는 아니지만 그와 같은 방식으로 걸러주면된다.

 

예를 들어 min=50 max=60 이 입력으로 주어지면

 1<a^2<=max 인 a에 대해서 그림과 같이 연산을 하면 남는것이 51 53 55 57 58 59로 6개가 되고 답이 6이 된다.

 

이 방법으로 아래코드를 작성했다.

 

코드

#define MAX 1000002
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <string.h>
typedef long long int ll;
using namespace std;
void setting();
ll a[MAX];
ll n,m;
int main(){
	cout.tie(NULL);
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    for(ll i=0; i<m-n+1; i++)
    {
        a[i]=i+n;
    }
    setting();
    ll ans=0;
    for(ll i=0; i<m-n+1; i++)
    {
        if(a[i]!=0)
        {
            ans++;
        }
    }
    cout<<ans;
}
void setting(){
    for(ll i=2; i*i<=m; i++)
    {
        ll x=(n/(i*i))*i*i;
        if(x==n)
        {
            for(ll j=0; ; j=j+i*i)
            {
                if(x-n+j>m-n)
                {
                    break;
                }
                a[x-n+j]=0;
            }
        }
        else
        {
            x=x+i*i;
            for(ll j=0; ; j=j+i*i)
            {
                if(x-n+j>m-n)
                {
                    break;
                }
                a[x-n+j]=0;
            }
        }
    }
}