abc271  A-F 题解
 
AtCoder-Beginner-Contest-271   A-F https://atcoder.jp/contests/abc271 
A - 484558 输出一个十进制数的十六进制表示(两位数),记得补0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include  <bits/stdc++.h>  using  namespace  std;char  c[] = {'A' , 'B' , 'C' , 'D' , 'E' , 'F' };int  main  ()   {    int  n;     cin >> n;     int  a = n / 16 , b = n % 16 ;     if  (a < 10 )     cout << a;     else     cout << c[a-10 ];     if  (b < 10 )     cout << b;     else     cout << c[b-10 ]; } 
 
B - Maintain Multiple Sequences 输出第n行第m列的数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include  <bits/stdc++.h>  using  namespace  std;int  main  ()   {    int  n, m;     cin >> n >> m;     vector <int > v[n];     for  (int  i = 0 ; i < n; i++) {         int  len;         cin >> len;         while  (len--) {             int  x;             cin >> x;             v[i].push_back  (x);         }     }     while  (m --) {         int  a, b;         cin >> a >> b;         a--, b--;         cout << v[a][b] << endl;     } } 
 
C - Manga 题意 按顺序 1,2,3,…n 读取序列,如果读到断开的地方,可以从序列中移走两个数,然后补上这个空位,问最多能读取多少书
分析 先把序列中小于等于n的存下来(因为是有可能被读取到的),读到中断的地方就把当前位置以及序列末尾的挪走(一种贪心的最优策略)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 3e5  + 5 ;bool  a[N];int  main  ()   {    int  n;     cin >> n;     for  (int  i = 1 ; i <= n; i++) {         int  x;         cin >> x;         if  (x <= n) a[x] = true ;     }     for  (int  i = 1 ; i <= n; i++) {         if  (!a[i])  n --;     }     cout << n; } 
 
D - Flip and Adjust 题意 n 张卡片,正反两面都是有数字,现在任意翻转摆放这 n 张卡片,问存不存在一种方案,使得正面和为 s 
分析 dp[i][j]: 选到第 i 张卡,总和为 j 的情况是否存在
依次转移,方案输出就是倒着推回去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 105 , M = 10005 ;int  a[N], b[N], n, m;int  f[N][M]; int  main  ()   {    cin >> n >> m;     for  (int  i = 1 ; i <= n; i++)    cin >> a[i] >> b[i];     memset  (f, -1 , sizeof  f);     f[0 ][0 ] = 1 ;     for  (int  i = 1 ; i <= n; i++) {         for  (int  j = 0 ; j <= m; j++) {             if  (f[i-1 ][j] == 1 ) {                 f[i][j+a[i]] = 1 ;                 f[i][j+b[i]] = 1 ;             }         }     }     if  (f[n][m] == 1 ) {         puts  ("Yes" );         string s;         if  (f[n-1 ][m-a[n]] == 1 )    m -= a[n], s += 'H' ;         else     m -= b[n], s += 'T' ;         for  (int  i = n - 1 , j = m; i >= 1 ; i--) {             if  (f[i][j] == 1  &&  f[i - 1 ][j - a[i]] == 1 )     s += 'H' , j -= a[i];              else  if  (f[i][j] == 1  &&  f[i - 1 ][j - b[i]] == 1 )   s += 'T' , j -= b[i];         }         reverse  (s.begin  (), s.end  ());         cout << s;     }     else     puts  ("No" ); } 
 
E - Subsequence Path 题意 现在有 n 个点, m 条带权有向边,现在我们给定一个序列 E 。现在要找一条 1-n 的,满足 是 E 子集的最短路径。
分析 松弛只会变小,全松弛一遍就是最优
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 2e5  + 5 ;long  long  f[N], a[N], b[N], w[N];int  main  ()   {    int  n, m, k;     cin >> n >> m >> k;     memset  (f, 0x3f , sizeof  f);     f[1 ] = 0 ;     for  (int  i = 1 ; i <= m; i++)    cin >> a[i] >> b[i] >> w[i];     for  (int  i = 1 ; i <= k; i++) {         int  x;         cin >> x;         f[b[x]] = min  (f[b[x]], f[a[x]] + w[x]);     }     if  (f[n] == f[0 ])     f[n] = -1 ;     cout << f[n]; } 
 
F - XOR on Grid Path 题意 有一个n *n 的地图,从 (1, 1) 走到 (n, n),每次只能向下或者向右走,问异或和为0的路径有多少条。
分析 n <= 20, 考虑爆搜,稍微优化:双向搜索(从两头开始搜, meet int the middle )
关于和的顺序问题:整个dfs过程看作一个栈,相当于是把两头合并在一起,所以sum错开来取即可,就是只加一次 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include  <bits/stdc++.h>  #define  int long long using  namespace  std;const  int  N = 25 ;int  a[N][N], n, ans;map <int , int > f[N]; void  dfs1  (int  x, int  y, int  sum)   {    sum ^= a[x][y];     if  (x + y == n + 1 ) {         f[x][sum] ++;         return  ;     }     dfs1  (x + 1 , y, sum), dfs1  (x, y + 1 , sum); } void  dfs2  (int  x, int  y, int  sum)   {    if  (x + y == n + 1 ) {         ans += f[x][sum];         return  ;     }     sum ^= a[x][y];     dfs2  (x - 1 , y, sum), dfs2  (x, y - 1 , sum); } signed  main  ()   {    cin >> n;     for  (int  i = 1 ; i <= n; i++) {         for  (int  j = 1 ; j <= n; j++)    cin >> a[i][j];     }     dfs1  (1 , 1 , 0 ), dfs2  (n, n, 0 );     cout << ans; }