2021暑假模拟赛2

A[HDU6954(1500)]

可以通过贪心的思想发现每个数连向自己的因数最优,那么只有质数是特殊的,所以筛出质数单独统计即可。

#include <bits/stdc++.h>
using namespace std;
vector<bool> GetPrime(int n) {
  vector<bool> mark(n + 1);
  vector<int> Prime;
  for (int i = 2; i <= n; ++i) {
    if (!mark[i]) {
      Prime.emplace_back(i);
    }
    for (int j = 0; j < Prime.size() && i * Prime[j] <= n; ++j) {
      mark[i * Prime[j]] = true;
      if (i % Prime[j] == 0) {
        break;
      }
    }
  }
  return mark;
}
int main() {
  int T;
  cin >> T;
  vector<bool> mark = GetPrime(10000000);
  while (T --> 0) {
    int N;
    cin >> N;
    long long Ans = 0;
    for (int i = 3; i <= N; ++i) {
      if (!mark[i]) {
        Ans += i * 2; 
      } else {
        Ans += i;
      }
    }
    cout << Ans << '\n';
  }
}
View Code

B[ABC179D(1251)]

考虑$dp$,$dp[i]$表示走到$i$的方案数,那么暴力转移枚举所有合法的$d$即可。但是这样会超时,于是用前缀和优化$dp$即可。

#include <bits/stdc++.h>

using namespace std;

const int P = 998244353;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    cin >> n >> k;

    vector<int> l(k);
    vector<int> r(k);
    for(int i = 0; i < k; ++i) {
        cin >> l[i] >> r[i];
    }

    vector<long long> dp(n + 1);
    vector<long long> pre(n + 1);

    dp[1] = 1;
    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j < k; ++j) {
            dp[i] += pre[max(0, i - l[j])] - pre[max(0, i - r[j] - 1)];
            dp[i] = (dp[i] % P + P) % P;
        }
        pre[i] = (pre[i - 1] + dp[i]) % P;
    }

    cout << dp[n] << '\n';

    return 0;
}
View Code

C[ABC164D(1232)]

考虑十进制的形式,可以发现类似字符串哈希,于是相当于求多少个子串的哈希值为2019倍数,于是利用前缀和优化计数即可。

#include <bits/stdc++.h>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string s;
    cin >> s;

    reverse(s.begin(), s.end());

    int sum = 0;

    map<int, int> mp;
    ++mp[0];

    long long ans = 0;
    long long pw = 1;

    for(char c : s) {
        sum = (sum + (c - '0') * pw) % 2019;
        pw = pw * 10 % 2019;
        ans += mp[sum];
        ++mp[sum];
    }

    cout << ans << '\n';    

    return 0;
}
View Code

D[CF1444B(1900)]

可以发现无论怎样分配,这个式子的和都是前$N$大的数-后$N$大的数,于是利用组合数统计即可。

#include <bits/stdc++.h>

using namespace std;

const int P = 998244353;

long long power(long long x, long long t) {
    long long ret = 1;
    for (; t; t >>= 1, x = x * x % P) {
        if (t & 1) {
            ret = ret * x % P;
        }
    }
    return ret;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<long long> a(n + n);
    for (int i = 0; i < n + n; ++i) {
        cin >> a[i];
    }

    sort(a.begin(), a.end());

    long long sum = 0;
    for (int i = 0; i < n; ++i) {
        sum = (sum + P - a[i]) % P;
    }
    for (int i = n; i < n + n; ++i) {
        sum = (sum + a[i]) % P;
    }

    for (int i = 1; i <= n + n; ++i) {
        sum = sum * i % P;
    }
    for (int i = 1; i <= n; ++i) {
        long long inv = power(i, P - 2);
        sum = sum * inv % P;
        sum = sum * inv % P;
    }

    cout << sum << '\n';

    return 0;
}
View Code

 

posted @ 2021-07-28 20:50  19992147  阅读(78)  评论(0编辑  收藏  举报