宜春学院水题赛题解

比赛入口

有一点尴尬,第一题出锅,比赛时改不了也通知不了,输出样例有问题,不能直接复制输出样例上的。


夯夯的祝福

做法:照顾新手的水题系列1,直接输出“Hello,World!”即可。

代码

#include<stdio.h>
int main() {
  printf("Hello, World!\n");
  return 0;
}

AC自动机fail指针上建可持久化线段树

做法:照顾新手的水题系列2,判断一个数是否是奇数。要看清哦,这个题目有两个坑点哦。

  1. 所有的字母‘O’都改成了数字’0’哦
  2. 数据范围很大哦,必须要用字符串形式哦
    判断一个数n是不是奇数:n%2==1 或者 n & 1 (二进制与运算,不知道的可以百度看看,很简单)

代码

#include<stdio.h>
#include<string.h>
int main() {
  char s[103];
  scanf("%s", s);
  int len = strlen(s);
  if((s[len-1]-'0') & 1) printf("B0B0 ZHEN SHUAI!\n");
  else printf("N0\n");
  return 0;
}

后缀自动机的next指针DAG图上求SG函数

做法:照顾新手的水题系列3,求出a数组中的最大值和次大值。用一个res1标记一下最大值,循环的每一次以res1为限制更新res2。

代码

#include<stdio.h>
const int INF = 1e9+7;
int main() {
  int res1 = -INF, res2 = -INF;
  int n, a;
  scanf("%d", &n);
  for(int i = 0; i < n; ++i) {
    scanf("%d", &a);
    if(res1 < a) {
      res2 = res1; res1 = a;
    } else if(res1 != a && res2 < a) res2 = a;
  }
  if(res1 != -INF && res2 != -INF) printf("%d %d\n", res1, res2);
  else printf("No answer\n");
	return 0;
}

夯夯和朱朱的异世界之旅

做法:照顾新手的水题系列4,一个数用二的次方和形式表示,求最少需要多少个二次方数以及最多需要多少个二次方数。最多的需求就是n本身,最少的需求就有多种解法了,详情请点击这里

代码

#include<stdio.h>
int main() {
  long long n, nn;
  while(~(scanf("%lld", &n))) {
    nn = n;
    int res = 0;
    while(nn) {
      if(nn % 2 == 1) res++;
      nn /= 2;
    }
    printf("%d %lld\n", res, n);
  }
	return 0;
}

朱朱的数论

做法:照顾新手的水题系列5,找一段序列循环节的最后一个数字,证明过程很繁杂,但是规律很好推出来,有公式 (p-a)%p,要注意a可能比p更大,要把答案变成正数,所以再加个p,再模一次p。

证明

  1. 若a与p不互质,那么显然,循环节一定是以开头的,那么前一个即是上一个循环的最后一个,也就是我们要求的答案,即(0-a) % p, 考虑到模数一定是正数,那么再加p 模 p即可。
  2. 若a与p互质,那么显然,他的循环节的开头也一定是0, 假设 a*x%p==0, 那么x的最小值就是p(a,p互质),所以答案还是((0-a)%p+p)%p。
  3. 即答案为 (-a %p + p) % p。

代码

#include<stdio.h>
int main() {
  int a, p;
  while(~scanf("%d%d", &a, &p)) {
  	printf("%d\n", ((-a % p) + p) % p);
  }
  return 0;
}

夯夯的棍棍

做法:dfs经典题目,若干长度不一样的木棒,将其拼成若干长度相等的木棒,求长度最小是多少。恩…可选棍子的长度应该在最长木棒与所有木棒长度之和之间,并且一定是总长的因数。然后再依次进行搜索即可。

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long ll;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int N = 70;
int n, sum, len, num, a[N], vis[N];
// n - n根棍子,sum - n根棍子的总长,len - 每根棍子的长度
//num - 一共有多少根len长度的棍子,a数组记录切割后棍子的长度,vis用于搜索
bool cmp(int x, int y) { return x > y; }
int dfs(int mid_num, int mid_len, int pos) {
  if(mid_num == num) return 1;  //如果棍子数量对上了
  if(mid_len == len) return dfs(mid_num+1, 0, 1);
  //如果长度够了,再拼接下一根棍子
  for(int i = pos; i <= n; ++i) {
    if(!vis[i] && mid_len + a[i] <= len) {
      vis[i] = 1;
      if(dfs(mid_num, mid_len + a[i], i + 1)) return 1;
      vis[i] = 0;
      if(mid_len == 0) return 0;
      while(i + 1 <= n && a[i+1] == a[i]) i++;
    }
  }
  return 0;
}
int main() {
  read(n);
  sum = 0;
  for(int i = 1; i <= n; ++i) {
    read(a[i]); sum += a[i];
  }
  sort(a+1, a+n+1, cmp); //从大至小排序,方便搜索
  int res = -1;
  for(int i = a[1]; i <= sum; ++i) {
    if(sum % i == 0) {
      memset(vis, 0, sizeof vis);
      len = i; num = sum / len;
      if(dfs(0, 0, 1)) { res = len; break; }
    }
  }
  printf("%d\n", res);
  return 0;
}

朱朱的图论

做法:给出起点和终点,问是否能找一条偶数路径。要知道,如果两点间能够到达,那么以这两个点组成的矩形中的数字必定是偶数。所以我们只需要判断这个矩形中的数字即可。其中还有一个很方便的操作,就是把这个数字模2。再根据 奇数+奇数 = 偶数 和 偶数+偶数 = 偶数,若这个矩形是全偶数矩形那么他在对应范围r,c范围内的和要么是0,要么全是1,前缀和处理一下即可。

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int N = 1e5+5;
int sumr[N], sumc[N];
int main() {
  int n, q;
  read(n); read(q);
  int r, c;
  for(int i = 1; i <= n; ++i) {
    read(r); r %= 2;
    sumr[i] = sumr[i-1] + r;
  }
  for(int i = 1; i <= n; ++i) {
    read(c); c %= 2;
    sumc[i] = sumc[i-1] + c;
  }
  int sx, sy, ex, ey, fx, fy;
  while(q--) {
    read(sx); read(sy); read(ex); read(ey);
    if(sx > ex) swap(sx, ex);
    if(sy > ey) swap(sy, ey);
    fx = sumr[ex] - sumr[sx-1]; fy = sumc[ey] - sumc[sy-1];
    if((fx == 0 && fy == 0) || (fx == ex - sx + 1 && fy == ey - sy + 1)) puts("YES");
    else puts("NO");
  }
}

夯夯的水题

做法:直接矩阵快速幂即可,题目具有迷惑性,想让你推出一个公式。

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int Mod = 1000000007;
struct xx {
  ll m[3][3];
  xx() { for(int i = 0; i < 3; ++i) memset(m[i], 0, sizeof m[i]); }
};
xx mul(xx a, xx b) {
  xx c;
  for(int i = 0; i < 2; ++i)
    for(int j = 0; j < 2; ++j) {
      c.m[i][j] = 0;
      for(int k = 0; k < 2; ++k)
        c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % Mod;
    }
    return c;
}
ll Pow(xx a, ll n) {
  xx res;
  res.m[0][0] = 1; res.m[1][1] = 1;
  while(n) {
    if(n & 1) res = mul(res, a);
    a = mul(a, a);
    n >>= 1;
  }
  return res.m[0][0];
}
int main() {
  ll n; read(n);
  xx a;
  a.m[0][0] = 1; a.m[0][1] = 1; a.m[1][0] = 1;
  ll f1 = Pow(a, n+2), f2 = Pow(a, n-2);
  printf("%lld\n",  (f1 * f1 % Mod - f2 * f2 % Mod + Mod) % Mod);
  return 0;
}
发布了28 篇原创文章 · 获赞 14 · 访问量 2967

猜你喜欢

转载自blog.csdn.net/qq_43408978/article/details/102855851