Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
传说 C~K 有三种神奇的魔法石:第一种魔法石叫做人铁石,拥有 A 的能量;第二种魔法石叫做地冈石,拥有 B 的能量;而第三种,则是最神奇的天玄石,拥有无可比拟的 C 的能量!
但是有一天,小豪宝宝 (UMR) 太调皮了,把一颗天玄石玩丢了……
“这可玩大发了,这样我会被 C~K 责备的。”小豪宝宝悲伤的说到,“怎么办呢?”
这时候小豪宝宝望了望窗外的飞过的白鸽,突然急中生智,想到了一个办法:干脆就用人铁石和地冈石把天玄石凑出来吧!
“只要我拿若干个人铁石,若干个地冈石,他们的能量之和,恰好加起来等于天玄石所拥有的能量。然后再把这些石头粘在一起,那么由若干个石头的组成的整体,我不就可以看做是一个天玄石了吗?“
小豪宝宝愈发觉得自己机智。
所以现在有一个问题摆在你的面前了,给你 A, B, C,请判断是否存在两个大于等于 0 的整数 x, y 满足 Ax+By=C。
Input
第一行一个 T,表示有 T 组测试数据。
接下来 T 行,每行三个整数 a, b, c,分别表示三块石头的能量值。
满足 (1 ≤ T ≤ 100, 1 ≤ a, b ≤ 100, 1 ≤ c ≤ 10 000)。
Output
对每一组测试答案均需要输出结果,如果可行的话,输出 "Yes",否则输出 "No"(不包括引号)。
Sample Input
Sample Output
15 | for ( int i=0; i<=h; i++) |
暴力一发就好了,枚举 A,看看有没有满足条件的 B
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
超市举行兑奖活动啦!!!
C~K 费劲心力,终于搞到了 m 张兑奖券,而奖品区有 n 件奖品,分别标号为 1~n,其中第 i 件奖品需要 need(i) 张奖券进行兑换,同时也只能兑换一次,为了辛苦得到的奖券不能够浪费,C~K 给每件奖品都评了分,其中第i件奖品的评分值为 value(i),表示 C~K 对这件奖品的喜好值,现在他想知道,凭借他手上的这些奖券,可以换到哪些奖品,使得这些奖品的喜好值最大。
Input
输入数据有多组(数据组数不超过 100),到 EOF 结束。
每一组测试数据第一行为两个正整数 n, m。表示奖品的个数及 C~K 手中的奖券数。
接下来 n 行描述每一行描述一个奖品,其中第 i 行为两个整数 need(i) 和 value(i),意义如前文所述。
(0 < n <= 500, 0 < m <= 10^5, 0 < need(i) <= 2*10^5, 0 < value(i) <= 10^3)
Output
对于每组输入的数据输出一个整数 ans,代表 C~K可 以获得的总喜好值。
Sample Input
Sample Output
1
我们很容易的就想到了记忆化搜索,我们用 best(n, m) 来表示有 n 件物品,奖券为 m 的张的时候,C~K 可以得到的最大的喜好值,那么我们只需要决定第 n 件物品选不选就可以了,所以我们很容易的就可以得到状态转移方程 best(n, m) = max(best(n-1, m), best(n, m-need(i))+value),分别对应着选与不选两种情况,但是现在又有一个问题,如果把 best 开成一个二维数组的话好像空间有点撑不太住,所以我们继续优化,我只需要开一个 m 大小的一维数组就可以了,如果我按照 j 从 m到 1 的顺序,也就是跟之前相反的顺序来进行计算的话,另外根据我们的状态转移方程,可以显然得出如果状态 (iA, jA) 依赖于状态 (iB, jB),那么肯定有 iA=iB+1, jA>jB,所以不难得出一个结论,我们在计算 best(i, j) 的时候,因为 best(i, j+1…m) 这些状态已经被计算过了,所以就意味着 best(i-1,k), k = j…m 这些值就都没有用了–所以依赖于他们的值都已经计算完了,于是他们原有的储存空间都可以用来春村别的东西,所以我们不妨就直接将 best(i, j) 的值存在 best(i-1, j) 原有的位置上,详见代码。
03 | int a[MAXN],need[MAXN],val[MAXN]; |
08 | while (~ scanf ( "%d%d" ,&n,&m)) |
10 | for ( int i=1; i<=n; i++) |
11 | scanf ( "%d%d" ,&need[i],&val[i]); |
12 | memset (a,0, sizeof (a)); |
13 | for ( int i=1; i<=n; i++) |
14 | for ( int j=m; j>=need[i]; j--) |
15 | a[j]=max(a[j],a[j-need[i]]+val[i]); |
类似背包,
03 | int a[MAXN],need[MAXN],val[MAXN]; |
08 | while (~ scanf ( "%d%d" ,&n,&m)) |
10 | for ( int i=1; i<=n; i++) |
11 | scanf ( "%d%d" ,&need[i],&val[i]); |
12 | memset (a,0, sizeof (a)); |
13 | for ( int i=1; i<=n; i++) |
14 | for ( int j=m; j>=need[i]; j--) |
15 | a[j]=max(a[j],a[j-need[i]]+val[i]); |
03 | int a[MAXN],need[MAXN],val[MAXN]; |
08 | while (~ scanf ( "%d%d" ,&n,&m)) |
10 | for ( int i=1; i<=n; i++) |
11 | scanf ( "%d%d" ,&need[i],&val[i]); |
12 | memset (a,0, sizeof (a)); |
13 | for ( int i=1; i<=n; i++) |
14 | for ( int j=m; j>=need[i]; j--) |
15 | a[j]=max(a[j],a[j-need[i]]+val[i]); |
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
bLue 这次又获得了一个更厉害的数组,欣喜之余,他想知道某个数字在数组中出现了多少次,你能帮助他吗?
Input
输入数据有多组(数据组数不超过 20),到 EOF 结束。
对于每组数据:
- 第 1 行输入 2 个用空格隔开的整数 n, q (1 <= n, q <= 10^5),分别表示数组中数字的个数和询问的次数。
- 第 2 行输入 n 个用空格隔开的整数 ai (0 <= ai <= 10^9),表示数组中的数字。
- 接下来 q 行,每行输入一个整数 v (0 <= v <= 10^9),表示要询问的数字。
Output
对于每组数据:
- 每次询问输出一行,包含一个整数,表示 bLue 询问的数字在数组中出现的次数。
- 每组数据末尾输出一行空行。
Sample Input
6 4
2 0 2 666 666 2
0
2
666
7
Sample Output
01 | #include<bits/stdc++.h> |
23 | for (p = h[i]; p; p = p->next) |
33 | while (~ scanf ( "%d %d" , &n, &m)) |
35 | for (i = 0; i < n; i++) |
39 | for (i = 0; i < n; i++) |
47 | printf ( "%d\n" , find(num)); |
03 | int a[MAXN],need[MAXN],val[MAXN]; |
08 | while (~ scanf ( "%d%d" ,&n,&m)) |
10 | for ( int i=1; i<=n; i++) |
11 | scanf ( "%d%d" ,&need[i],&val[i]); |
12 | memset (a,0, sizeof (a)); |
13 | for ( int i=1; i<=n; i++) |
14 | for ( int j=m; j>=need[i]; j--) |
15 | a[j]=max(a[j],a[j-need[i]]+val[i]); |
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
在古老而神秘的 409 实验室,住着一位史诗级长者,世人称之为「金桔」。
金桔能歌善舞,能说会道,能写伸展树,会敲自动机,口算微积分,心算大反演,区域赛虐遍全场,傲得了娇卖得了萌,实乃 ACM 界之集大成长者。
最近,临近退役的金桔自觉体弱多衰,身子骨一日不如一日,常常自言自语道:“唉,我已经是一只废桔了...”。现在,他连基本的查找大于等于 n 的素数都不会了,为了冲 Final,他只能求助于你,你能帮助金桔吗?
Input
输入数据有多组(数据组数不超过 100000),到 EOF 结束。
每组数据输入一行,包含一个整数 n (0 <= n < 5000000)。
Output
对于每组数据,输出一行,包含用空格隔开的两个整数 i, v,表示大于或等于 n 的第一个素数的相关信息。其中 i 表示此素数是第几个素数,v 表示此素数是多少。
Sample Input
Sample Output
1 2
1 2
2 3
3 5
173 1031
345 2333
#include <stdio.h>
#include <stdbool.h>
#define MAXN 5000000
int prime[1000000], cnt = 1;
bool is_composite[MAXN];
// 素数筛
void Sieve() {
for(int i=2; i<MAXN; ++i) {
if(!is_composite[i]) prime[cnt++] = i;
for(int j=1; j<cnt && i*prime[j]<MAXN; ++j) {
is_composite[i*prime[j]] = true;
if(i%prime[j] == 0) break;
}
}
}
// 二分查找
int BinarySearch(int a[], int low, int high, int key) {
int mid = (low+high)/2;
if(low >= high) return low;
else {
if(key < a[mid])
return BinarySearch(a, low, mid-1, key);
else if(key > a[mid])
return BinarySearch(a, mid+1, high, key);
else return mid;
}
}
int main() {
Sieve();
int n;
while(~ scanf("%d", &n)) {
int idx = BinarySearch(prime, 1, cnt, n);
if(prime[idx] < n) idx++;
printf("%d %d\n", idx, prime[idx]);
}
return 0;
}
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
一天,刚打完 CF 的 bLue 决定来一场说走就走的旅行,于是他拿出了地图开始制定行程。
在地图上,bLue 和目的地之间可以用一条直线来表示,他自己在坐标为 0 的位置,而目的地在坐标为 n 的位置。
bLue 计划花费 d 天到达目的地,旅途中,他每天只能选择前进 1, 2, 3 或 4 个单位距离,而不能向回走。他想知道有多少种方案能使他恰好花费 d 天到达目的地。
例如:目的地的坐标为 4,计划天数为 3,则 bLue 有 "1, 2, 4", "1, 3, 4", "2, 3, 4" 三种方案。
Input
输入数据有多组(数据组数不超过 10000),到 EOF 结束。
每组数据输入一行,包含 2 个整数 n, d (0 <= n <= 20, 0 <= d < 10^6),分别代表目的地的位置和 bLue 花费的天数。
Output
Sample Input
Sample Output
// DFS Version
#include <stdio.h>
int n, d, now_n, now_d, ans;
void DFS(int now_n, int now_d) {
if(now_n > n) return;
if(now_d > d) return;
if(now_n==n && now_d==d) {
ans++;
return;
}
// 向下一步的四种情况递归
DFS(now_n+1, now_d+1);
DFS(now_n+2, now_d+1);
DFS(now_n+3, now_d+1);
DFS(now_n+4, now_d+1);
}
int main() {
while(~ scanf("%d %d", &n, &d)) {
if(d > n) { // d > n 直接输出 0
printf("0\n");
continue;
}
ans = 0; // ans 记录答案
DFS(0, 0);
printf("%d\n", ans);
}
return 0;
}
// DP Version
#include <stdio.h>
int max(int a, int b) {
return a>b ? a : b;
}
int main() {
int n, d, dp[21][21] = {0};
dp[0][0] = 1;
for(int i=1; i<=20; ++i) {
for(int j=1; j<=20; ++j) {
for(int k=max(i-4,0); k<=i-1; ++k) { // 上一天所在的位置只能是 i-4 到 i-1
dp[i][j] += dp[k][j-1];
}
}
}
while(~ scanf("%d %d", &n, &d)) {
if(d > n) { // d > n 直接输出 0
printf("0\n");
continue;
}
printf("%d\n", dp[n][d]);
}
return 0;
}
// DP Version
#include <stdio.h>
int max(int a, int b) {
return a>b ? a : b;
}
int main() {
int n, d, dp[21][21] = {0};
dp[0][0] = 1;
for(int i=1; i<=20; ++i) {
for(int j=1; j<=20; ++j) {
for(int k=max(i-4,0); k<=i-1; ++k) { // 上一天所在的位置只能是 i-4 到 i-1
dp[i][j] += dp[k][j-1];
}
}
}
while(~ scanf("%d %d", &n, &d)) {
if(d > n) { // d > n 直接输出 0
printf("0\n");
continue;
}
printf("%d\n", dp[n][d]);
}
return 0;
}
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
bLue 的电脑里存了各种各样的文件,随着文件越来越多,查找文件也成了一个麻烦事。
现在,他想要查找所有指定格式(扩展名)的文件,不过他并不会使用文件管理器自带的搜索功能,所以他想求你写一个文件查找器,来帮他查找所有指定格式的文件。
Input
输入数据有多组(数据组数不超过 100),到 EOF 结束。
对于每组数据:
- 第一行输入一个整数 n (1 <= n <= 100) 和一个长度不超过 5 的字符串 ex,分别表示文件夹内的文件数量和要查找的文件的扩展名。
- 接下来的 n 行,每行输入一个完整文件名。保证文件名不包含空格且长度不超过 100。
Output
对于每组数据,按照输入顺序输出文件夹内所有扩展名符合查找要求的文件名。
Sample Input
6 cpp
3717.cpp
xunhuansai_daima.zip
xunhuansai_jietibaogao.pdf
C.cpp
bLue.jpg
cyk_de_richang.mp4
Sample Output
// DP Version
#include <stdio.h>
int max(int a, int b) {
return a>b ? a : b;
}
int main() {
int n, d, dp[21][21] = {0};
dp[0][0] = 1;
for(int i=1; i<=20; ++i) {
for(int j=1; j<=20; ++j) {
for(int k=max(i-4,0); k<=i-1; ++k) { // 上一天所在的位置只能是 i-4 到 i-1
dp[i][j] += dp[k][j-1];
}
}
}
while(~ scanf("%d %d", &n, &d)) {
if(d > n) { // d > n 直接输出 0
printf("0\n");
continue;
}
printf("%d\n", dp[n][d]);
}
return 0;
}
#include <stdio.h>
#include <string.h>
int main() {
int n;
char s[101], s_ex[6], ex[6];
while(~ scanf("%d %s", &n, ex)) {
for(int i=0; i<n; ++i) {
scanf("%s", s);
for(int i=0; s[i]; ++i) {
if(s[i] == '.') {
strcpy(s_ex, s+i+1); // 截取扩展名到 s_ex
if(!strcmp(s_ex, ex)) printf("%s\n", s);
break;
}
}
}
}
return 0;
}
// DP Version
#include <stdio.h>
int max(int a, int b) {
return a>b ? a : b;
}
int main() {
int n, d, dp[21][21] = {0};
dp[0][0] = 1;
for(int i=1; i<=20; ++i) {
for(int j=1; j<=20; ++j) {
for(int k=max(i-4,0); k<=i-1; ++k) { // 上一天所在的位置只能是 i-4 到 i-1
dp[i][j] += dp[k][j-1];
}
}
}
while(~ scanf("%d %d", &n, &d)) {
if(d > n) { // d > n 直接输出 0
printf("0\n");
continue;
}
printf("%d\n", dp[n][d]);
}
return 0;
}