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;
}