루오 구 1450 : 동전 쇼핑

루오 구 1450 : 동전 쇼핑

주제 설명 :

  • 의 교단에서 동전의 네 가지 명칭이있다 (C1, C2, C3, C4는 \) \ .
  • 가게에 사람의 이동은 총에, 물건을 구입 (\ T) \ , 시간이 될 때마다 (d_i \) \ 조각 \ (C_I \) 동전, 구매 가치 \ (s_i \) , 얼마나 많은 각 질문 뭔가를 지불 방법.

데이터 범위 :

  • \ (d_i, s_i \ 당량 1E5 \)
  • \ TOT (\는 \ 1,000 당량)

아이디어 :

  • 포함 및 제외 배낭 +
  • 각각의 질문은 여러 배낭을 할 것, 그것은 확실히 나올 것입니다.
  • 우리가 먼저 각 동전이 발생 무제한 사용할 수있는 경우 어떻게되는지 살펴 보자.
  • 배낭 완전히 즉, 사용할 수있는 (F (I) \) \ 동전의 수를 선택하기 위해 각 프로그램을 임의의 횟수를 나타내고, 전사 식있다 \ (F (J) = F (JC (I)) \) .
  • 첫째 단 하나의 동전의 경우를 생각해 보자.
  • 여기에 프로그램의 수 이상 수 있습니다 (D \) \ A는, 그 결과는 사용이있을 수 있습니다 \ (D + 1, D + 2, ... \) 우리가 필요하므로, 프로그램의 상황의 종류 그는 뺀다.
  • 여기에 예제를주고, 그것을 어떻게, 지금은 두 개의 섹션이 있다고 ([2 + \ infin \ ] \) 및 ([3 + \ Infin] \) \ . 내가 싶어 \ ([2,3] \) 난 그냥이 두 간격을 빼기해야 할 영역.
  • 그런 다음 우리는 마이너스 선택, 선거는 프로그램의 수를 고려할 필요가 \ (D + 1 \) 동전 프로그램을.
  • 이어서 알 \ (ANS = F (S) - (F (S) -C * (D + 1)). \) . 이러한는 선택의 여지가 선거 무한 마이너스입니다 \ (D + 1 \) 입니다.
  • 동전의 다양한있다 \ (ANS = F (S) - \ sum_ = {I} 제 1} ^ {F (S-C_I * (D_i + 1)). \.) .
  • 그러나이 공식은 그가 때문에 가능한 종, 직접 첨가제 아니라, 단지 감각 (1 \) \ 동전은 제한 유형을 초과 \ (2 \) 동전 한계를 초과하고, 축적 중복 상황에 직접 이어질 것입니다.
  • 이 필요한 포함 - 배제 법칙은 그래서 당신이 직접 열거하지만, 비트 연산 열거에 훨씬 쉽게 될 것입니다 수 있습니다, 물론, 네 개의 동전이 있습니다.

코드 :

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int c[5], d[5], s, T;
ll f[maxn], ans;

int main()
{
    for(int i = 1; i <= 4; i++) scanf("%d", &c[i]);
    f[0] = 1;
    for(int i = 1; i <= 4; i++)
        for(int j = c[i]; j <= maxn-5; j++)
            f[j] += f[j-c[i]];

    scanf("%d", &T);
    while(T--)
    {
        ll ans = 0;
        for(int i = 1; i <= 4; i++)
            scanf("%d", &d[i]);
        scanf("%d", &s);
        ans = f[s];
        for(int i = 1; i < (1<<4); i++)
        {
            ll tmp = 0, num = 0;
            for(int j = 1; j <= 4; j++)
            {
                if((1<<(j-1))&i)
                {
                    num++;
                    tmp += (d[j]+1) * c[j];
                }
            }
            if(tmp > s) continue;
            if(num % 2 == 0) ans += f[s-tmp];
            else ans -= f[s-tmp];
        }
        cout << ans << endl;
    }

    return 0;
}

추천

출처www.cnblogs.com/zxytxdy/p/12063893.html