You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2023_02_1_week;
// 一共有 4 种硬币。面值分别为c1、c2、c3、c4
// 一开始就给定了,就是这些面值不再改变
// 某人去商店买东西,去了 n 次,
// 每次都是一次查询:
// 这个人每次代的每种硬币的数量不一样都记录在d数组中
// 1) d[i]表示他带了的i种面值的数量
// 2) 他要购买s价值的东西
// 返回每次有多少种购买方法
// 1 <= c1、c2、c3、c4、d[i]、s <= 10^5
// 1 <= n <= 1000
// 测试链接 : https://www.luogu.com.cn/problem/P1450
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code提交时请把类名改成"Main"
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Code04_FourKindsPaperQueryWays {
public static int limit = 100000;
// 无限制情况下的方法数得到dp
// 可以用这个dp去求解2元 交上 3元的违规方法
public static long[] dp = new long[limit + 1];
public static int[] c = new int[4];
public static int[] d = new int[4];
public static int n, s;
public static void init() {
dp[0] = 1;
for (int i = 0; i <= 3; i++) {
for (int j = c[i]; j <= limit; j++) {
dp[j] += dp[j - c[i]];
}
}
}
public static long query() {
// 违规方法数!
long minus = 0;
// d c b a
// 0 0 0 1
// 0 1 1 0
for (int status = 1; status <= 15; status++) {
// 100元2元 4张 3元 9张
// 100 - 2 * 5 - 3 * 10 => 60
// 60元无限制的情况下方法数是多少
// 就是100元在2元面值和3元面值同时违规的情况下违规方法数
long t = s;
int sign = -1;
for (int j = 0; j <= 3; j++) {
// j 0号货币有没有
// 1号货币有没有
// 2号货币有没有
// 3号货币有没有
if (((status >> j) & 1) == 1) {
t -= c[j] * (d[j] + 1);
sign = -sign;
}
}
if (t >= 0) {
minus += dp[(int) t] * sign;
}
}
return dp[s] - minus;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
// 先给每一种面值
// 存好,可能有多组查询,但是有哪些面值是不变的
// 面值的种数也不变4种面值
c[0] = (int) in.nval;
in.nextToken();
c[1] = (int) in.nval;
in.nextToken();
c[2] = (int) in.nval;
in.nextToken();
c[3] = (int) in.nval;
in.nextToken();
// 有多少组查询
n = (int) in.nval;
init();
for (int i = 0; i < n; i++) {
// 一组查询
// a 面值 给你多少张
// b 面值 给你多少张
// c 面值 给你多少张
// d 面值 给你多少张
in.nextToken();
d[0] = (int) in.nval;
in.nextToken();
d[1] = (int) in.nval;
in.nextToken();
d[2] = (int) in.nval;
in.nextToken();
d[3] = (int) in.nval;
in.nextToken();
// 花钱总数
// 不超过10的5次方的
s = (int) in.nval;
out.println(query());
out.flush();
}
}
}
}