补题:牛客寒假算法基础集训营1

比赛入口


H nozomi和字符串

做法:用两个队列,通过维护size+k大小的滑动窗口更新答案。

代码

#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;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
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;
}
queue<int> q[2];
int main() {
  int n, k;
  string s;
  cin >> n >> k >> s;
  int res = 0;
  for(int i = 0; i < n; ++i) {
    char mid = s[i] - '0';
    q[mid].push(i);
    if(q[mid].back() - q[mid].front() + 1 > q[mid].size() + k) q[mid].pop();
    res = q[mid].size() + k;
  }
  if(res > n) res = n;
  cout << res << endl;
  return 0;
}

I nico和niconiconi

做法:简单dp递推一下就好啦…当时怎么就没看这题呢…

代码

#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;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
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 = 3e5+5;
LL dp[N];
int main() {
  int n, a, b, c;
  cin >> n >> a >> b >> c;
  string s; cin >> s;
  for(int i = 0; i < n; ++i) {
    dp[i] = dp[i-1];
    if(i >= 3 && s.substr(i-3, 4) == "nico") dp[i] = max(dp[i], dp[i-3] + a);
    if(i >= 5 && s.substr(i-5, 6) == "niconi") dp[i] = max(dp[i], dp[i-5] + b);
    if(i >= 9 && s.substr(i-9, 10) == "niconiconi") dp[i] = max(dp[i], dp[i-9] + c);
  }
  cout << dp[n-1] << endl;
  return 0;
}

J u’s的影响力

做法:思路很简单,指数取模Mod-1就行,因为0次方时要输出0总是90分过不去…细节问题比较多

代码

#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;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
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 maxn = 4;
const LL Mod = 1e9+7;
struct mat {
  LL m[maxn][maxn];
  mat() {
    for(int i = 0; i < maxn; ++i)
      for(int j = 0; j < maxn; ++j)
        m[i][j] = 0;
  }
};
mat matmul(mat a,mat b) {
  mat ans;
  for(int i=1; i<maxn; i++) {
    for(int j=1; j<maxn; j++) {
      for(int k=1; k<maxn; k++) {
        ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j]%(Mod-1))%(Mod-1);
      }
    }
  }
  return ans;
}
mat QuickPow(mat a,LL n) {
  mat res;
  for(int i=1;i<=3;i++)    res.m[i][i]=1;
  while(n) {
    if(n&1) res=matmul(a, res);
    a = matmul(a,a);
    n >>= 1;
  }
  return res;
}
LL ksm(LL x, LL n) {
  x %= Mod;
  if(!n) return 0;
  LL sum = 1;
  while(n) {
    if(n & 1) sum = sum * x % Mod;
    x = x * x % Mod;
    n >>= 1;
  }
  return sum;
}
int main() {
  LL n, x, y, a, b;
  cin >> n >> x >> y >> a >> b;
  x %= Mod; y %= Mod;
  if(n == 1) { cout << x << endl; return 0; }
  if(n == 2) { cout << y << endl; return 0; }
  mat mid, res;
  LL res1, res2, res3;
  mid.m[1][1] = mid.m[1][2] = mid.m[1][3] = mid.m[2][1] = mid.m[3][3] = 1;
  res = QuickPow(mid, n-2);
  res1 = res.m[1][2]; res2 = res.m[1][1]; res3 = res.m[1][3];
  cout << ksm(x, res1) * ksm(y, res2) % Mod * ksm(ksm(a, b), res3) % Mod << endl;
  return 0;
}


F maki和tree

做法:有两种情况,端点为白点和白点,白点和黑点,把黑点周围的白点连通块sum求出来,第一种的结果用容斥得到,为该黑点周围白点连通块任意两白点构成的数量减去单个连通块内的任意两白点构成的数量(这里的端点为两白点的就不经过黑点了),第二种就是sum啦…

代码

#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;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
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;
LL sum, ans, t1, t2;
char s[N];
vector<int> ve[N];
void dfs(int u, int fa) {
  if(s[u] == 'B') return ;
  sum++;
  for(int i = 0; i < ve[u].size(); ++i) {
    if(ve[u][i] != fa) dfs(ve[u][i], u);
  }
}
int main() {
  int n;
  scanf("%d%s", &n, s+1);
  for(int i = 1, u, v; i < n; ++i) {
    scanf("%d%d", &u, &v);
    ve[u].push_back(v);
    ve[v].push_back(u);
  }
  for(int i = 1; i <= n; ++i) {
    t1 = t2 = 0;
    if(s[i] == 'W') continue;
    for(int j = 0; j < ve[i].size(); ++j) {
      sum = 0;
      dfs(ve[i][j], ve[i][j]);
      ans += sum;
      t1 += sum; t2 += sum * sum;
    }
    ans += (t1 * t1 - t2) / 2;
  }
  printf("%lld\n", ans);
  return 0;
}

C umi和弓道

做法:是个滑动窗口??

发布了28 篇原创文章 · 获赞 14 · 访问量 2947

猜你喜欢

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