algorithm

BOJ 5615

rkawk 2024. 3. 15. 17:56

문제

더보기

μ•„νŒŒνŠΈ μž„λŒ€ μ„±κ³΅λ‹€κ΅­μ–΄

문제

λ™κ·œλΆ€λ™μ‚°μ—μ„œ μ•„νŒŒνŠΈλ₯Ό μž„λŒ€ν•˜κ³  μžˆλ‹€. μ•„νŒŒνŠΈμ˜ 방은 μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 면적이 2xy + x + y이닀. (x와 yλŠ” μ–‘μ˜ μ •μˆ˜)

λ™κ·œλΆ€λ™μ‚°μ˜ μΉ΄νƒˆλ‘œκ·Έμ—λŠ” μ•„νŒŒνŠΈμ˜ 면적이 μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ ν˜€μ Έ μžˆμ§€λ§Œ, 이 쀑 μΌλΆ€λŠ” μžˆμ„ 수 μ—†λŠ” 크기의 μ•„νŒŒνŠΈμ΄λ‹€. λ§Œμ•½, 이런 크기의 μ•„νŒŒνŠΈλ₯Ό μž„λŒ€ν•˜κ² λ‹€κ³  λ§ν•˜λ©΄, λ™κ·œλŠ” 꽝! 이라고 μ™ΈμΉ˜λ©΄μ„œ, 수수료만 λ–Όμ–΄κ°„λ‹€.

λ™κ·œλΆ€λ™μ‚°μ˜ μΉ΄νƒˆλ‘œκ·Έμ— 적힌 μ•„νŒŒνŠΈμ˜ 면적이 μ£Όμ–΄μ‘Œμ„ λ•Œ, μžˆμ„ 수 μ—†λŠ” 크기의 μ•„νŒŒνŠΈμ˜ 수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 μ•„νŒŒνŠΈμ˜ 면적의 수 N이 μ£Όμ–΄μ§„λ‹€. λ‹€μŒ 쀄뢀터 N개 쀄에 μΉ΄νƒˆλ‘œκ·Έμ— μ ν˜€μžˆλŠ” μˆœμ„œλŒ€λ‘œ 면적이 μ£Όμ–΄μ§„λ‹€. N은 100,000μ΄ν•˜μ΄κ³  면적은 231-1μ΄ν•˜μΈ μ–‘μ˜ μ •μˆ˜μ΄λ‹€.

좜λ ₯

첫째 쀄에 μžˆμ„ 수 μ—†λŠ” μ•„νŒŒνŠΈ 면적의 수λ₯Ό 좜λ ₯ν•œλ‹€.

풀이

2xy + x + y  = S 라 ν–ˆμ„λ•Œ, (2x+1)(2y+1) = 2S+1둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. x, y의 λ²”μœ„κ°€ μ–‘μ˜ μ •μˆ˜μ΄λ―€λ‘œ 2S+1은 무쑰건 ν•©μ„±μˆ˜μ΄λ‹€. κ·ΈλŸ¬λ―€λ‘œ μž…λ ₯받은 S에 λŒ€ν•΄μ„œ 2S+1이 μ†Œμˆ˜μΈ 경우, μ •λ‹΅ 카운트λ₯Ό ν•˜λ‚˜ 올렀주면 λœλ‹€.

 

#include <iostream>
using namespace std;
#define ll unsigned long long 
ll N, ans;
int a_param[5] = {2, 3, 5, 7, 11};
ll power(ll x, ll y, ll mod) {
    ll result = 1;
    x %= mod;
    while(y) {
        if(y%2) result = (result*x)%mod;
        y/=2;
        x = (x*x)%mod;
    }
    return result;
}
bool miller(ll n, ll a) {
    if(a%n == 0) return false;
    ll k = n-1;
    while(1) {
        ll temp = power(a, k, n);
        if(temp == n-1) return true;
        if(k%2) return (temp == 1 || temp == -1);
        k /= 2;
    }
}

int isPrime(ll n) {
    if(n == 2 || n == 3) return true;
    if(n%2 == 0 || n == 1) return false;
    for(int i=0; i<5; i++) {
        ll a = a_param[i];
        if(a == n) return true;
        if(!miller(n, a)) return false;
    }
    return true;
}

int main() {
    cin>>N;
    while(N--) {
        ll S; cin>>S;
        if(isPrime(2*S+1)) ans += 1;
    }
    cout<<ans;
}