SRM 625 DIV2

1. 250-point
(1). 题意
对于给定的 y, 找到 3 个数 x0, x1, x2, 满足:
(a).  x0 * x1 + x2 = y
(b). -1000 <= xi <= 1000;  i 为 0, 1, 2
(c). xi != 0 && xi != 1;  i 为 0, 1, 2
(2). 思路
(a). 两层 for 循环, 每层都是从 -1000 到 1000, 第一层是 x0, 第二层是 x1, 确保 x0, x1 满足 (1).(c)
(b). 按 y - x0 * x1 = x2
(c). 若 x2 满足 (1) 中的 (b), (c), 则为所求
(3). 代码 
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <limits>
#include <bitset>
using namespace std;

class AddMultiply{
  public:
  vector <int> makeExpression(int y) {

    for (int i=-1000; i<=1000; i++) {
      for (int j=-1000; j<=1000; j++) {
        if (i == 0 || i == 1 || j == 0 || j == 1) continue;

        int k = y - i * j;
        if (k != 0 && k != 1 && k >= -1000 && k <= 1000) {
          vector<int> vt;
          vt.push_back(i);
          vt.push_back(j);
          vt.push_back(k);
          return vt;
        }
      }
    }
  }
};
2. 500-point
(1). 题意

给定数组 vector<int> A 及整数 k , 假设 A 中包含 N 个元素, 每次可以取 A 中的任意数, 把这个数加上 k, 可以进行任意次取数加k的操作, 但每个数只能加不能减, 问最后是否能生成数组 1, 2, 3, ... N?
(2). 思路
(a). 把 A 从小到大进行排序
(b). 按从 1 到 N 逐个数进行生成, 每次要生成的数为 n
(c). 每次从已排好序的 A 中, 按从大到小进行取数, 看取到的数是否能满足 (n-A[j]) % k == 0, 若满足,则说明此 A[j] 将被用来生成 n, 并将 A[j] 标识为已使用
(d). 若有某一个 n 找不到适合的 A[j] 来递增 k 来得到, 则说明 IMPOSSIBLE
(3). 代码 

#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <limits>
#include <bitset>
using namespace std;

class IncrementingSequence{
  public:
  string canItBeDone(int k, vector <int> A) {
    // vt[i] 不为 0表示第 A[i] 个已经被使用了
    vector<int> vt;
    for (int i=0; i<A.size(); i++) {
      vt.push_back(0);
    }

    // 从小到大排序
    sort(A.begin(), A.end());

    // 从大于小, 每个 n 都判断是否能取到一个 A[j]
    // 满足 (n-A[j]) % k == 0
    // 若有不能满足的 n, 则为 IMPOSSIBLE
    for (int n=1; n<=A.size(); n++) {
      bool checked = false;
      // 要先用大的
      for (int j=0; j<A.size(); j++) {
        if (vt[j] == 0 && n >= A[j] && (n-A[j]) % k == 0) {
          checked = true;
          vt[j] = 1;
          break;
        }
      }

      if (!checked) return "IMPOSSIBLE";
    }

    return "POSSIBLE";
  }
};
(4). 补充
在 (2) 的 (c) 中, 说了是要从大于小进行取数, 刚才试了一下, 从小到大, 也是能 PASS SYSTEM TEST 的; 当初最开始提交的时候, 就是按从小到大取数进行提交的, 后来又重新提交了一次, 改成从大到小取数, 被扣了 50 分啊; 不然这次分数应应能涨一些的...

3. 950-point
(1). 题意
大家围成一圈, 按顺时针方向进行编号0, 1, 2, .. N-1, 其中有一些人是诚实人, 专说真话; 有一些人是撒谎人, 专说假话, 现在对每个人都有可能进行提问, 第 i 个人会有以下3种回答:
(a). 'L' 表示 i 说第 i+1个人是撒谎者
(b). 'H' 表示 i 说第 i+1个人是诚实人
(c). '?' 表示没有问到第 i 个人
对于给定的包含 'L', 'H', '?' 的字符串, 判断可能存在的最小的撒谎者个数, 若无法判断, 则返回 -1.
(2). 思路
注: 见官方题解
(3). 代码
见官方题解.

4. 官方题解

你可能感兴趣的:(topcoder,SRM,625)