补题:吉首大学第九届"新星杯"大学生程序设计大赛 ---还差一题.jpg

为了督促自己补题!以后都开博客记录!

本次比赛:吉首大学第九届"新星杯"大学生程序设计大赛(重现赛)
时间:2020/1/5

共做出8题,最后卡在了一道博弈题。

A:比赛的时侯看了下题目,没看懂,然后跳了。其实也很简单,意思就是,如果这次找到了,那么下一次的起点就变成了这个点,下一次我们直接减去它就可以了。

///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template  inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair
#define fi first
#define se second
set se[13];
int main() {
  int x, y, z, q, a;
  read(x); read(y); read(z);
  se[0].insert(0);
  for(int i = 1; i <= 12; i++) {
    for(auto it : se[i-1]) {
      se[i].insert(it + x);
      se[i].insert(it - x);
      se[i].insert(it + y);
      se[i].insert(it - y);
      se[i].insert(it + z);
      se[i].insert(it - z);
    }
  }
  int st = 0;
  read(q);
  while(q--) {
    read(a);
    a = a - st;
    if(se[12].find(a) != se[12].end()) {
      puts("YES");
      st = abs(a);
    }
    else {
      puts("NO");
      st = 0;
    }
  }
}

B: 签到题,不谈。

C:写的时侯看错了题目, wa了几发才发现读错了题目。实际上只会移动一次。然后打标记在判断即可

D:二分答案即可

E:签到题

F:比赛的时侯没有看0.0,n很大,所有肯定有点规律,n > 178之后 模数就变成0了,发现这个就很简单了

///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair
#define fi first
#define se second
const LL Mod = 3777105087;
LL arr[200];
int main() { 
  LL n, x, y;
  arr[1] = 1;
  _rep(2, 178, i) arr[i] = (arr[i-1] * i) % Mod;
  while(cin >> n >> x >> y) { 
     if(n >= 178) n = 178;
     LL ret = 0;
     _rep(2, n, i) {
       ret = (ret + arr[i]) % Mod;
     }
     if(y) _rep(1, x, i) ret = ret * 2 % Mod;
     ret = (ret + 1) % Mod;
     cout << ret << "\n";
  } 
} 

G: DP,是我做不出来的题。。在题解和AC代码的帮助下把这题补了;

一个显然的结论,一个数的位数大的一定大于位数小的。所以难求的就是等于的情况。dp[i][j][k],1 <= i <=n, 1 <= j <= m, 0 <= k <= 1;
k为0 时代表 一个串的第i个匹配到另一个串的第j个时,大于它的个数
k为1时代表 一个串的第i个匹配到另一个串的第j个时,等于它的个数
然后发现每一个状态都是从上一个状态转移过来的,所以空间是可以优化的,可以用滚动数组。然后再发现只能从上一个状态中长度较小的转移到较大的,所以实际上逆序一下就可以了;
转移方程:
dp[j][0] += dp[j-1][0] 大于的到这里还是大于
dp[j][1] += dp[j-1][1] s[i] == t[j]; 相等的到这里还是相等
dp[j][0] += dp[j-1][1] s[i] > t[j];现在相等的也变成大于的了

最后dp[m][0] 就是答案。但是这得m >= n 的时侯。因为我们少算了一部分,当n >= m 时,长度为 m + 1 到 n 的都是一定大于的,但是前面统计不到。所以还得DP一次长度为 i 的数字的个数,不能有前导0;

dp[i][j] 代表前i个中,长度为 j 的有多少个。
转移方程:
dp[i][j] += dp[i-1][j-1]
dp[i][1] += s[i] != ‘0’;

本着优化的精神 我们发现和上面一样的,逆序一下就可以变成一维。然后再把大于m + 1的部分加到答案中就可以。

#include
using namespace std;
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
const int N = 3e3+5;
const int Mod = 998244353;
int dp[N][2], dp1[N];
char s[N], t[N];
inline int min(int a, int b) {
  return a < b ? a : b;
}
inline void Mov(int &a, int b) {
  a += b;
  if(a > Mod) a -= Mod;
}
int main() {
  int k;
  read(k);
  while(k--) {
    memset(dp, 0, sizeof dp);
    memset(dp1, 0, sizeof dp1);
    int n, m;
    read(n); read(m);
    scanf("%s %s", s +  1, t + 1);
    dp[0][1] = 1;
    _rep(1, n, i) 
      for(int j = min(i, m); j >= 1; --j) {
        if(s[i] == t[j]) Mov(dp[j][1], dp[j-1][1]);
        if(s[i] > t[j]) Mov(dp[j][0], dp[j-1][1]);
        Mov(dp[j][0], dp[j-1][0]);
      }
    _rep(1, n, i) {
      for(int j = i; j >= 1; --j) {
        if(j == 1) dp1[1] += s[i] != '0';
        else Mov(dp1[j], dp1[j-1]);
      }
    }
    _rep(m+1, n, i) Mov(dp[m][0], dp1[i]);
    printf("%d\n", dp[m][0]);
  }
} 

H:模拟即可

I:二进制中1的数量

J:思维题,找最长的连续递增子序列,n减之即可

K:并查集

L:

M:
刚开始写了下深搜,推了个假结论。还是以前没有搞清楚SG函数的作用。其实就是道SG函数的裸题。SG(n)为真即真。

///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair
#define fi first
#define se second
const int N = 1e3+5;
int Sg[N], vis[N], a[N];
int n, m;
bool SG(int n) {
  for(int i = 1; i <= n; i++) {
    memset(vis, 0, sizeof vis);
    for(int j = 1; j <= m; j++) {
      if(i - a[j] >= 0) vis[Sg[i - a[j]]] = 1;
    }
    for(int j = 0; j <= n; j++) {
      if(!vis[j]) {
        Sg[i] = j;break;
      }
    }
  }
  return Sg[n];
}
int main() {
  read(n); read(m);
  for(int i = 1; i <= m; i++) read(a[i]);
  if(SG(n)) puts("Y");
  else puts("N");
}

你可能感兴趣的:(补题)