2020 CCPC Wannafly Winter Camp Day1

重新补补题, 顺便保存下题目, 整合一下, 以前写的太乱了

A

题面

题解

代码

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;

const int mod = 998244353;

bool cmp(PII a, PII b)
{
    return a.fi + a.se < b.fi + b.se;
}

int quick(int a, int b)
{
    int ans = 1;
    for (; b; b >>= 1, a = 1ll * a * a % mod)
        if (b & 1) ans = 1ll * ans * a % mod;
    return ans;
}

int calc(PII a, PII b)
{
    int l = max(a.fi, b.fi);
    if (a.se < l) return 0;
    int r = min(a.se, b.se);
    int ans = 1ll * (l - b.fi + r - b.fi) * (r - l + 1) / 2 % mod;
    ans = (ans + 1ll * (a.se - r) * (b.se - b.fi + 1)) % mod;
    return ans;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n, ans = 0; cin >> n;
    vector<PII> a(n);
    VI inv(n);
    rep (i, 0, n - 1) cin >> a[i].fi >> a[i].se;
    sort(all(a), cmp);
    rep (i, 0, inv.size() - 1) inv[i] = quick(a[i].se - a[i].fi + 1, mod - 2);
    rep (i, 0, n - 1)
        rep (j, i + 1, n - 1)
            ans = (ans + 1ll * inv[i] * inv[j] % mod * calc(a[i], a[j]) % mod) % mod;
    cout << ans << '\n'; 
    return 0;
}

B

题面

题解

没啥好说的, 逆着做

代码

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define IO ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;

const int N = 1e5 + 5;

int n, m, _, k;
PII a[1001];
string s[1001];

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> n >> m;

    rep(i, 1, m) cin >> a[i].fi >> a[i].se;

    rep(i, 1, n) cin >> s[i];

    per(i, m, 1) {
        string& x = s[a[i].fi], &y = s[a[i].se];

        rep(j, 0, y.size() - 1) {
            int idb = y[j] - 'a' + (y[j] < 'a' ? 58 : 0), ida = j % x.size();
            ida = x[ida] - 'a' + (x[ida] < 'a' ? 58 : 0);

            idb = (idb + 52 - ida) % 52;
            y[j] = 'a' + idb - (idb < 26 ? 0 : 58);
        }
    }

    rep(i, 1, n) cout << s[i] << '\n';

    return 0;
}

C

题面

我啥时候能自己不看题解写出来阿

题解

1.对于 k >= n 的 g(n, k) = C(n, 2)

2.对于 k < n, 设每种颜色图的点的数量为\(c_i\), g(n, k) = C(n, 2) - \(\sum\)C(\(c_i\), 2)

想要 g 最大, 明显要将 n 平均分成 k 份

有$\left \lceil n / k \right \rceil $个点的 有 n - \(\left \lfloor n / k \right \rfloor\) * k 个

\(\left \lfloor n / k \right \rfloor\)个点的, 有 k - (n - \(\left \lfloor n / k \right \rfloor\) * k) 个

所以 g(n, k) = C(n, 2) - (n - \(\left \lfloor n / k \right \rfloor\) * k) * C($\left \lceil n / k \right \rceil $, 2) - (k - (n - \(\left \lfloor n / k \right \rfloor\) * k)) * C(k - (n - \(\left \lfloor n / k \right \rfloor\) * k), 2)

而我们知道 $\left \lceil n / k \right \rceil $ = \(\left \lfloor (n - 1) / k \right \rfloor\) + 1

所以我们就能化简了,

然后O(n)求 g 是超时的

我们发现其实可以将 [l, r] 分段, 使得段内 \(\left \lfloor (n - 1) / k \right \rfloor\)\(\left \lfloor n / k \right \rfloor\) 相等

然后利用求和公式算就行了

代码

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define IO ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;

const int N = 1e5 + 5;
const int mod = 998244353;
 
int t, n, l, r, _;
 
int get(int l, int r) {
    int k1 = (n - 1) / l + 1, kk1 = (1ll * k1 * (k1 - 1) >> 1) % mod;
    int k2 = n / l, kk2 = (1ll * k2 * (k2 - 1) / 2) % mod;
    int len = r - l + 1, lenj = (1ll * (l + r) * len >> 1) % mod;
    int ans = 1ll * len * kk1 % mod * n % mod;
    ans = (ans - 1ll * k2 * kk1 % mod * lenj % mod + mod) % mod;
    ans = (ans + 1ll * (k2 + 1) * lenj % mod * kk2 % mod) % mod;
    ans = (ans - 1ll * n * kk2 % mod * len % mod + mod) % mod;
    return ans;
}
 
void work() {
    ll ans = 0;
    for(int i = l, ne; i <= r && i < n; i = ne + 1) {
        ne = min(n / (n / i), (n - 1) / ((n - 1) / i));  //给定正整数i和n满足i<=n,使得n/i=n/x成立的最大的x为n/(n/i)
        ne = min(ne, r);
        ans = (ans + get(i, ne)) % mod;
    }
    ans = (((1ll * (n - 1) * n) >> 1) % mod * (r - l + 1) % mod - ans + mod) % mod;
    cout << ans << '\n';
}
 
int main()
{
    ios::sync_with_stdio(0); cin.tie(0);
    for (cin >> _; _; --_) {
        cin >> n >> l >> r;
        work();
    }
    return 0;
}
posted @ 2020-07-22 15:49  洛绫璃  阅读(173)  评论(0编辑  收藏  举报