训练赛(Older)#001
题解(F):
1不知道 二维多重背包。。。
2多重背包模板题
3完全背包模板题
4线段树求区间最值 模板题
5幂取模乱搞
6DFS
7水题
8水题
ID | Origin | Title | ||
---|---|---|---|---|
2 / 14 | Problem A | HDU 3496 | Watch The Movie | |
10 / 23 | Problem B | HDU 2191 | 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 | |
8 / 11 | Problem C | HDU 4508 | 湫湫系列故事――减肥记I | |
5 / 9 | Problem D | POJ 3264 | Balanced Lineup | |
6 / 22 | Problem E | HDU 4506 | 小明系列故事――师兄帮帮忙 | |
4 / 5 | Problem F | HDU 2181 | 哈密顿绕行世界问题 | |
4 / 6 | Problem G | POJ 3210 | Coins | |
7 / 7 | Problem H | POJ 3094 | Quicksum |
B
1 8 2 2 100 4 4 100 2
400
思路:多重背包模板题
转换为01背包思想
procedure MultiplePack(cost,weight,amount)
if cost*amount>=V
CompletePack(cost,weight)
return
integer k=1
while k<num
ZeroOnePack(k*cost,k*weight)
amount=amount-k
k=k*2
ZeroOnePack(amount*cost,amount*weight)
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn = 110; const int Maxn = 20*100+10; int dp[maxn]; int n,m; int N; int v[Maxn],w[Maxn]; struct Node{ int v,w,c; }t[maxn]; int main() { int a,b,e; int T; int n,m; scanf("%d",&T); while(T--) { int N = 0; memset(dp,0,sizeof(dp)); scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) { scanf("%d%d%d", &a, &b,&e); t[i].v=a; t[i].w=b; t[i].c=e; N+=e; } int k = 0; int s= 0; for(int i = 0; i < m; i++) { k = 1; while(k<20 && t[i].c >= k) { v[s] = t[i].v*k; w[s++] = t[i].w*k; t[i].c -= k; k = k*2; } v[s] = t[i].v*t[i].c; w[s++] = t[i].w*t[i].c; } for(int i = 0; i < s; i++) { for(int j = n; j >= v[i]; j--) dp[j] = max(dp[j], dp[j-v[i]]+w[i]); } printf("%d\n", dp[n]); } return 0; }
C
3 3 3 7 7 9 9 10 5 1 1 5 3 10 3 6 8 7 5 6
10 20
思路:完全背包模板题
procedure CompletePack(cost,weight)
for v=cost..V
f[v]=max{f[v],f[v-c[i]]+w[i]}
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100000+10; int dp[maxn]; int w[110],v[110]; int n,m; int main() { while(scanf("%d", &n) != EOF) { memset(dp,0,sizeof(dp)); //int a,b; for(int i = 0; i < n; i++) { scanf("%d%d", &w[i], &v[i]); } scanf("%d", &m); for(int i = 0; i < n; i++) { for(int j = v[i]; j <=m; j++) dp[j] = max(dp[j], dp[j-v[i]]+w[i]); } printf("%d\n", dp[m]); } return 0; }
D
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 26485 | Accepted: 12426 | |
Case Time Limit: 2000MS |
Description
For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.
Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.
Input
Output
Sample Input
6 3 1 7 3 4 2 5 1 5 4 6 2 2
Sample Output
6 3 0
Source
思路:区间最值问题。
详细分析见:POJ 3264 区间最值模板题
/* *Accepted *8404 KB *3579 ms *G++ *1022 B 2013-03-23 21:57:28 *O(n*logn) *第一次写RMQ套用lrj的模板,效率较低,模板较坑 Orz */ #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn = 50000+10; int d_max[maxn][20]; int d_min[maxn][20]; int A[maxn]; int n,q; void RMQ_init() { for(int i = 1; i <= n; i++) d_max[i][0] = d_min[i][0] = A[i]; for(int j = 1; j <= log((double)(n+1))/log(2.0); j++) for(int i = 1; i+(1<<j)-1 <= n; i++) { d_min[i][j] = min(d_min[i][j-1], d_min[i + (1<<(j-1))][j-1]); d_max[i][j] = max(d_max[i][j-1], d_max[i + (1<<(j-1))][j-1]); } } int RMQ_Max(int L, int R) { int k = (int)(log((double)(R-L+1)) / log(2.0)); return max(d_max[L][k], d_max[R-(1 << k)+1][k]); } int RMQ_Min(int L, int R) { int k = (int)(log((double)(R-L+1)) / log(2.0)); return min(d_min[L][k], d_min[R-(1 << k)+1][k]); } int main() { while(scanf("%d%d", &n, &q) != EOF) { for(int i = 1; i <= n; i++) scanf("%d", &A[i]); RMQ_init(); int a,b; for(int i = 1; i <= q; i++) { scanf("%d%d", &a, &b); printf("%d\n",RMQ_Max(a,b) - RMQ_Min(a,b)); } } return 0; }
E
2 3 2 5 1 2 3 3 0 5 1 2 3
50 75 25 1 2 3
思路:幂取模问题。
先将数组元素乘以 k^t %mod ,然后再对应于数组元素个数 n 确定其周期性,根据 t%n 顺时针旋转来确定首位置。
(PS:测试时注意首位置不要比 n 大)。
注意:整数的溢出(int *int 可能会超int)
循环输出时,首位置的确定,最好用下面那组数据测试一下,否则WA到正无穷啊
#include<cstdio> const int maxn = 10000+10; const int mod = 1000000000+7; int a[maxn]; int n,t,k; int mul(int m,int n)//m^n { int b = 1; while(n>0) { if(n&1) b = ((long long)b*m)%mod; n = n >>1; m = ((long long)m*m)%mod; } return (int)b; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d%d", &n, &t, &k); for(int i = 1; i <= n; i++) scanf("%d",&a[i]); int temp = mul(k,t); for(int i = 1; i <= n; i++) { a[i] = ((long long)a[i]*temp)%mod; a[i] = (int)a[i]; } t%=n; int x =(n-t+1) ; if(x>n) x%=n;//printf("%d\n",x); for(int i = x; i <= n; i++) { if(i == x) printf("%d",a[i]); else printf(" %d",a[i]); } for(int i=1; i < x; i++) printf(" %d",a[i]); printf("\n"); //printf("\n");// } return 0; } /* 6 4 1 1 1 2 3 4 4 2 1 1 2 3 4 4 3 1 1 2 3 4 4 4 1 1 2 3 4 4 5 1 1 2 3 4 4 6 1 1 2 3 4 */
F
2 5 20 1 3 12 2 4 10 3 5 8 1 4 6 5 7 19 6 8 17 4 7 9 8 10 16 3 9 11 10 12 15 2 11 13 12 14 20 13 15 18 11 14 16 9 15 17 7 16 18 14 17 19 6 18 20 1 13 19 5 0
1: 5 1 2 3 4 8 7 17 18 14 15 16 9 10 11 12 13 20 19 6 5 2: 5 1 2 3 4 8 9 10 11 12 13 20 19 18 14 15 16 17 7 6 5 3: 5 1 2 3 10 9 16 17 18 14 15 11 12 13 20 19 6 7 8 4 5 4: 5 1 2 3 10 11 12 13 20 19 6 7 17 18 14 15 16 9 8 4 5 5: 5 1 2 12 11 10 3 4 8 9 16 15 14 13 20 19 18 17 7 6 5 6: 5 1 2 12 11 15 14 13 20 19 18 17 16 9 10 3 4 8 7 6 5 7: 5 1 2 12 11 15 16 9 10 3 4 8 7 17 18 14 13 20 19 6 5 8: 5 1 2 12 11 15 16 17 18 14 13 20 19 6 7 8 9 10 3 4 5 9: 5 1 2 12 13 20 19 6 7 8 9 16 17 18 14 15 11 10 3 4 5 10: 5 1 2 12 13 20 19 18 14 15 11 10 3 4 8 9 16 17 7 6 5 11: 5 1 20 13 12 2 3 4 8 7 17 16 9 10 11 15 14 18 19 6 5 12: 5 1 20 13 12 2 3 10 11 15 14 18 19 6 7 17 16 9 8 4 5 13: 5 1 20 13 14 15 11 12 2 3 10 9 16 17 18 19 6 7 8 4 5 14: 5 1 20 13 14 15 16 9 10 11 12 2 3 4 8 7 17 18 19 6 5 15: 5 1 20 13 14 15 16 17 18 19 6 7 8 9 10 11 12 2 3 4 5 16: 5 1 20 13 14 18 19 6 7 17 16 15 11 12 2 3 10 9 8 4 5 17: 5 1 20 19 6 7 8 9 10 11 15 16 17 18 14 13 12 2 3 4 5 18: 5 1 20 19 6 7 17 18 14 13 12 2 3 10 11 15 16 9 8 4 5 19: 5 1 20 19 18 14 13 12 2 3 4 8 9 10 11 15 16 17 7 6 5 20: 5 1 20 19 18 17 16 9 10 11 15 14 13 12 2 3 4 8 7 6 5 21: 5 4 3 2 1 20 13 12 11 10 9 8 7 17 16 15 14 18 19 6 5 22: 5 4 3 2 1 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 23: 5 4 3 2 12 11 10 9 8 7 6 19 18 17 16 15 14 13 20 1 5 24: 5 4 3 2 12 13 14 18 17 16 15 11 10 9 8 7 6 19 20 1 5 25: 5 4 3 10 9 8 7 6 19 20 13 14 18 17 16 15 11 12 2 1 5 26: 5 4 3 10 9 8 7 17 16 15 11 12 2 1 20 13 14 18 19 6 5 27: 5 4 3 10 11 12 2 1 20 13 14 15 16 9 8 7 17 18 19 6 5 28: 5 4 3 10 11 15 14 13 12 2 1 20 19 18 17 16 9 8 7 6 5 29: 5 4 3 10 11 15 14 18 17 16 9 8 7 6 19 20 13 12 2 1 5 30: 5 4 3 10 11 15 16 9 8 7 17 18 14 13 12 2 1 20 19 6 5 31: 5 4 8 7 6 19 18 17 16 9 10 3 2 12 11 15 14 13 20 1 5 32: 5 4 8 7 6 19 20 13 12 11 15 14 18 17 16 9 10 3 2 1 5 33: 5 4 8 7 17 16 9 10 3 2 1 20 13 12 11 15 14 18 19 6 5 34: 5 4 8 7 17 18 14 13 12 11 15 16 9 10 3 2 1 20 19 6 5 35: 5 4 8 9 10 3 2 1 20 19 18 14 13 12 11 15 16 17 7 6 5 36: 5 4 8 9 10 3 2 12 11 15 16 17 7 6 19 18 14 13 20 1 5 37: 5 4 8 9 16 15 11 10 3 2 12 13 14 18 17 7 6 19 20 1 5 38: 5 4 8 9 16 15 14 13 12 11 10 3 2 1 20 19 18 17 7 6 5 39: 5 4 8 9 16 15 14 18 17 7 6 19 20 13 12 11 10 3 2 1 5 40: 5 4 8 9 16 17 7 6 19 18 14 15 11 10 3 2 12 13 20 1 5 41: 5 6 7 8 4 3 2 12 13 14 15 11 10 9 16 17 18 19 20 1 5 42: 5 6 7 8 4 3 10 9 16 17 18 19 20 13 14 15 11 12 2 1 5 43: 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1 2 3 4 5 44: 5 6 7 8 9 16 17 18 19 20 1 2 12 13 14 15 11 10 3 4 5 45: 5 6 7 17 16 9 8 4 3 10 11 15 14 18 19 20 13 12 2 1 5 46: 5 6 7 17 16 15 11 10 9 8 4 3 2 12 13 14 18 19 20 1 5 47: 5 6 7 17 16 15 11 12 13 14 18 19 20 1 2 3 10 9 8 4 5 48: 5 6 7 17 16 15 14 18 19 20 13 12 11 10 9 8 4 3 2 1 5 49: 5 6 7 17 18 19 20 1 2 3 10 11 12 13 14 15 16 9 8 4 5 50: 5 6 7 17 18 19 20 13 14 15 16 9 8 4 3 10 11 12 2 1 5 51: 5 6 19 18 14 13 20 1 2 12 11 15 16 17 7 8 9 10 3 4 5 52: 5 6 19 18 14 15 11 10 9 16 17 7 8 4 3 2 12 13 20 1 5 53: 5 6 19 18 14 15 11 12 13 20 1 2 3 10 9 16 17 7 8 4 5 54: 5 6 19 18 14 15 16 17 7 8 9 10 11 12 13 20 1 2 3 4 5 55: 5 6 19 18 17 7 8 4 3 2 12 11 10 9 16 15 14 13 20 1 5 56: 5 6 19 18 17 7 8 9 16 15 14 13 20 1 2 12 11 10 3 4 5 57: 5 6 19 20 1 2 3 10 9 16 15 11 12 13 14 18 17 7 8 4 5 58: 5 6 19 20 1 2 12 13 14 18 17 7 8 9 16 15 11 10 3 4 5 59: 5 6 19 20 13 12 11 10 9 16 15 14 18 17 7 8 4 3 2 1 5 60: 5 6 19 20 13 14 18 17 7 8 4 3 10 9 16 15 11 12 2 1 5
思路:简单DFS应用,记录路径。注意格式和输出顺序要先给点排序,还有就是执行dfs的条件要注意下,我标记了的。
/* *F *Accepted *204 KB *0 ms *G++ *867 B *2013-03-26 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int path[22]; int point[21][3]; bool vis[21]; int m; int Case; void dfs(int a, int n) { vis[a] = true; path[n] = a; if(n == 21 && path[n] == m) //回到起点 { printf("%d: ",++Case); for(int i = 1; i <= 21; i++) printf(" %d", path[i]); printf("\n"); return; } else if(n >= 21) return; for(int i = 0; i < 3; i++) { int x = point[a][i]; if((x != m && !vis[x]) || (x == m && n == 20)) //如果没有走过,或者下一个点回到起点 { //注意:前一个条件如果没有写 x != m 则会影响后面的结果 也就是 m 会在路径中重复出现 dfs(x, n+1); vis[x] = false; } } } int main() { for(int i = 1; i <= 20; i++) { scanf("%d%d%d", &point[i][0], &point[i][1], &point[i][2]); sort(point[i], point[i]+3); } while(scanf("%d", &m) != EOF) { Case = 0; if(m == 0) break; memset(vis, false, sizeof(vis)); dfs(m, 1); } return 0; }
G
Time Limit: 1000MS | Memory Limit: 131072K | |
Total Submissions: 6465 | Accepted: 4215 |
Description
Snoopy has three coins. One day he tossed them on a table then and tried to flip some of them so that they had either all heads or all tails facing up. After several attempts, he found that regardless of the initial configuration of the coins, he could always achieve the goal by doing exactly two flippings, under the condition that only one coin could be flipped each time and a coin could be flipped more than once. He also noticed that he could never succeed with less than two flippings.
Snoopy then wondered, if he had n coins, was there a minimum number x such that he could do exactly x flippings to satisfy his requirements?
Input
The input contains multiple test cases. Each test case consists of a single positive integer n (n < 10,000) on a separate line. A zero indicates the end of input and should not be processed.
Output
For each test case output a single line containing your answer without leading or trailing spaces. If the answer does not exist, output “No Solution!
”
Sample Input
2 3 0
Sample Output
No Solution! 2
Source
比赛时实在没看懂是什么意思,现在想起,就算当时看懂了也应该不会想到这儿吧。。。下面copy个牛人的分析。
分析来自:点击打开链接
题意:Snoopy想问下,若有n枚硬币,这n枚硬币的初始状态是任意的,则至少需要翻转几次,才能保证对于任何一种初始状态而 言,都能变成n枚硬币全为正或全为反。
思路:若n为偶数:
1: 若初始状态为偶数正面 + 偶数反面,要想变成全正或全反,翻转的次数必为偶数。
例如: ○○●●●● 则翻转 2,4,6,8……次均可。
2: 若初始状态为奇数正面 + 奇数反面,要想变成全正或全反,翻转的次数必为奇数。
例如: ○○○○○● 则翻转 1,3(先将●翻为○,再将任一个○翻两下),5,7……次均可。
因次,我们就无法得到一个确定的翻转次数x,让它能使任意初始状态的硬币变成全为正或全为反,因为若x为偶数,则无法满足例2,若x为奇数,则无法满足例1。故应输出"No Solution!"。
若n为奇数:
初始状态只可能为偶数正面 + 奇数反面(偶数反面 + 奇数正面同理),故要想变成全正或全反,是必能找出一个次数x满足所有任意情况的。
1:对初始状态即全为奇数个正面而言,翻转的次数必为偶数。
2: 由1得只能翻所有正面为反面,因为这样才需翻转偶数次。
例如: ○○○○●●● 则翻转4,6,8,10……次均可,其中最小为4。要保证对7枚硬币的任意初始状态都可行,则最小应为 7-1=6 ,否则对 ○○○○○○● 无法实现。
因此,当你为奇数是,最少翻转次数为n-1。
源代码:(这题考的是题意和推理,不是代码)
/* *Accepted *132 KB *0 ms *C++ *176 B */ #include<cstdio> int main() { int n; while(scanf("%d", &n) != EOF) { if(n == 0) break; if(n%2 == 0) printf("No Solution!\n"); else printf("%d\n", n-1); } return 0; }
H
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11832 | Accepted: 8152 |
Description
A checksum is an algorithm that scans a packet of data and returns a single number. The idea is that if the packet is changed, the checksum will also change, so checksums are often used for detecting transmission errors, validating document contents, and in many other situations where it is necessary to detect undesirable changes in data.
For this problem, you will implement a checksum algorithm called Quicksum. A Quicksum packet allows only uppercase letters and spaces. It always begins and ends with an uppercase letter. Otherwise, spaces and letters can occur in any combination, including consecutive spaces.
A Quicksum is the sum of the products of each character's position in the packet times the character's value. A space has a value of zero, while letters have a value equal to their position in the alphabet. So, A=1, B=2, etc., through Z=26. Here are example Quicksum calculations for the packets "ACM
" and "MID CENTRAL
":
ACM: 1*1 + 2*3 + 3*13 = 46 MID CENTRAL: 1*13 + 2*9 + 3*4 + 4*0 + 5*3 + 6*5 + 7*14 + 8*20 + 9*18 + 10*1 + 11*12 = 650
Input
The input consists of one or more packets followed by a line containing only # that signals the end of the input. Each packet is on a line by itself, does not begin or end with a space, and contains from 1 to 255 characters.
Output
For each packet, output its Quicksum on a separate line in the output.
Sample Input
ACM MID CENTRAL REGIONAL PROGRAMMING CONTEST ACN A C M ABC BBC #
Sample Output
46 650 4690 49 75 14 15
Source
思路:字符串简单处理,直接看代码即可,注意空格的处理就好了。
#include<cstdio> #include<cstring> char s[300]; int main() { char c; int ans = 0;; while((c=getchar()) != '#') { ans = 0; int k = 0; memset(s,-1,sizeof(s)); if(c != '\n') { if(c != ' ') s[k++] = c -'A'+1; else s[k++] = 0; } while((c=getchar()) != '\n') { if(c != ' ') s[k++] = c -'A'+1; else s[k++] = 0; } for(int i = 0; i < k; i++) {//printf("%d ",s[k]) ans += s[i]*(i+1); } printf("%d\n", ans); ans = 0; k = 0; memset(s,-1,sizeof(s)); } return 0; }