2023. 6. 4. 18:53, 알고리즘/BOJ
i의 범위를 잡을때 long long 범위를 벗어나지 않기 위해서 i<=b/p로 작성하는 부분을 보고,
i*p>=a도 그러한 형태로 작성할 수있지 않을까 싶어서 그렇게 수정하고 제출했을때 통과가 안되는걸 보고 어떠한 차이점이 있길래 이건 안되고 저건 되는가에 대해서 스스로 생각해보고, 그 이유에 대해서 적어보았다.
#include <bits/stdc++.h>
using namespace std;
vector<int> sieve(int n){
vector<int> primes;
vector<bool> state(n+1,true);
state[1]=false;
for(int i=2; i*i<=n; i++){
if(!state[i]) continue;
for(int j=i*i;j<=n; j+=i)
state[j]=false;
}
for(int i=2; i<=n; i++){
if(state[i]) primes.push_back(i);
}
return primes;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
vector<int> primes=sieve(10000000);
long long a, b;
cin>>a>>b;
int cnt=0;
for(int p:primes){
for(long long i = p; i<=b/p; i*=p)
cnt+=(i*p>=a); //이 부분을 cnt+=(i>=a/p); 로 작성하면 틀린다. 왜인가
/*
i*p<=b를 i<=b/p로 작성하는 것이나, i*p>=a를 i>=a/p로 작성하는것이나 똑같아 보일 수 있다.
그러나 막상 엄밀하게 계산해보면, i<=b/p는 결국 인트값으로 잘려 날라가는 오차값을 생각해볼때,
잘려 나가는 오차값이 존재하더라도 작거나 같은 범위이기 때문에 결국 정수로 정의된 i 값에서
선택될 수 있는 i값이 달라지는 부분이 없다.
그런데 i>=a/p는 범위를 더 작은 범위까지 늘려버리기 때문에 오차가 발생한다
예를들어 i>=1.25 형태라고 할때, 이건 i가 정수이기 때문에 가능한 경우는 i=2,3,4, 형태라고
볼 수 있는데, 이때에 c++에서 int 혹은 long long 의 정수 형태로 타입을 선언한뒤
5/4 형태로 계산하면 이건 1이 되어버려서 이때에 i가
가능한 값은 i=1,2,3,4,... 형태로 1이 의도와는 다르게 가능한 영역이 되어버린다.
그래서 이 경우에는 만약 위의 경우에 p가 저 사이 간극에 하나라도 가능한게 있다면 틀려버리게
되는 것이다.
그래서 이 경우 등호의 방향이 i<=b/p이니까 가능한 방식의 연산이고,
i*p>=a 형태는 그런식으로 해서는 잘못된 i가 포함 가능하게 되어버리는 것이다.
*/
}
cout<<cnt;
}
'알고리즘 > BOJ' 카테고리의 다른 글
boj 5347번 문제 LCM을 통해 배우게 되는 계산 중간 과정에서의 int overflow의 가능성. 그리고 해결법 세가지. (0) | 2023.06.05 |
---|---|
boj 2312번 문제를 통해서 한참 잘못빠져들었던 에라토스테네스의 체의 구현 . (0) | 2023.06.05 |
boj 10610번 문제를 통해 정말 오랜만에 접해보는 3의 배수인지 아닌지 판단하는 판단법에 관하여. (0) | 2023.06.03 |
boj 2869번 문제를 통해 알게된 코드에서의 ( )을 통한 우선순위 두기. (0) | 2023.06.03 |
boj 9613번 문제를 통해 배우는 type 설정의 중요성. (0) | 2023.06.03 |
Comments, Trackbacks