题目大意:给你n个宿舍的可以容纳的人数和现在已住的人数,问有几个宿舍可以安排两个人进去住。
解法:模拟,无trick。
代码:
1 #include <cstdio> 2 3 int main() { 4 int n; 5 while(scanf("%d", &n) != EOF){ 6 int a, b, ans = 0; 7 for(int i = 0; i < n; i++) { 8 scanf("%d%d", &a, &b); 9 if(b - a >= 2) ans++; 10 } 11 printf("%d ", ans); 12 } 13 14 return 0; 15 }
题目大意:给你m+1个数,问前m个数的二进制和最后一个数不同的位数小于等于k个的数的个数。
解法:模拟,无trick。求不同的位数可先异或然后看有多少个1。
代码:
1 #include <cstdio> 2 3 int a[1010]; 4 5 int main() { 6 int n, m, k; 7 while(scanf("%d%d%d", &n, &m, &k) != EOF){ 8 int ans = 0; 9 for(int i = 0; i < m; i++) scanf("%d", &a[i]); 10 scanf("%d", &a[m]); 11 for(int i = 0; i < m; i++) { 12 int p = a[i] ^ a[m], t = 0; 13 while(p > 0) { 14 if(p % 2 == 1) t++; 15 p /= 2; 16 } 17 if(t <= k) ans++; 18 } 19 printf("%d ", ans); 20 } 21 22 return 0; 23 }
题目大意:从n个数中选出m段不相交的子串,子串的长度均为k,问所有选出来的子串的所有数的和最大为多少。
解法:DP即可。dp[i][j]表示从前i个数选出j段的最大和,转移很明显。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[5010]; long long s[5010], dp[5010][5010]; int main() { int n, m, k; while(scanf("%d%d%d", &n, &m, &k) != EOF){ int ans = 0; s[0] = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); s[i] = s[i - 1] + a[i]; } for(int i = m; i <= n; i++) { for(int j = k; j >= 1; j--) dp[i][j] = max(dp[i - 1][j], dp[i - m][j - 1] + s[i] - s[i - m]); } printf("%I64d ", dp[n][k]); } return 0; }
题目大意:给你一篇由一些单词构成的文章,单词不区分大小写。再给你一些单词的转化关系,即单词a可以被单词b替换(注意是单向的,sb出题人写input里面算什么!)。你可以无限的进行替换操作,现在希望被替换后的文章r的数量最少,在此基础上总长度最短。
解法:显然如果是一个DAG的话我们就可以直接对每个点进行记忆化搜索来更新答案,对这道题显然可以进行缩点,新的点的属性由这个强联通分量里面r最小的情况下最短的单词决定。但是对于这道题的情况我们可以不缩点,按照点的大小关系(即先看r的数量最少的,r一样的情况下看最短的)进行dfs也是正确的(当然直接记忆化搜索是错的,在环的更新上会出现问题)。
代码:
#include <cstdio> #include <map> #include <cstring> #include <vector> #include <string> #include <algorithm> using namespace std; const int N = 100010; struct Node { int r, l, p; }g[5 * N]; int ar[5 * N], al[5 * N], u[5 * N]; map<string, int> mp; char s[5 * N], t[5 * N]; vector<int> e[5 * N], lis; int calc(char q[]) { int res = 0; for(int i = 0; q[i] != '