Day 1
物理实验
转一下坐标系,扫描线,用set可以维护出每一段的最低位置能看到的线段的斜率,然后再双指针扫一遍就行了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 10005;
const LD eps = 1e-9;
struct Point {
LD x, y;
Point(LD x = 0, LD y = 0):x(x), y(y) {}
Point operator - (const Point &b) const {
return Point(x - b.x, y - b.y);
}
} c, d, a[N], b[N];
struct Line {
Point l, r;
int i;
Line(Point l = Point(0, 0), Point r = Point(0, 0), int i = -1):l(l), r(r), i(i) {}
inline LD F(LD x) const {
return ((x - l.x) * r.y + (r.x - x) * l.y) / (r.x - l.x);
}
inline LD S() const {
return sqrt(1 + ((r.y - l.y) * (r.y - l.y)) / ((r.x - l.x) * (r.x - l.x)));
}
bool operator < (const Line &b) const {
LD x = max(l.x, b.l.x);
return fabs(F(x)) < fabs(b.F(x));
}
} l[N];
LD all, ans, v[N << 1], x[N << 1];
pair <LD, int> eve[N << 1];
set <Line> s, t;
int n, m;
int Main() {
Read(n), m = 0, ans = 0, s.clear(), t.clear();
for (int i = 1; i <= n; ++i) {
Read(a[i].x), Read(a[i].y), Read(b[i].x), Read(b[i].y);
}
Read(c.x), Read(c.y), Read(d.x), Read(d.y), Read(all), d = d - c;
LD p, q, len = sqrt(d.x * d.x + d.y * d.y);
for (int i = 1; i <= n; ++i) {
a[i] = a[i] - c;
p = (d.x * a[i].x + d.y * a[i].y) / len, q = (d.x * a[i].y - d.y * a[i].x) / len;
a[i] = Point(p, q);
b[i] = b[i] - c;
p = (d.x * b[i].x + d.y * b[i].y) / len, q = (d.x * b[i].y - d.y * b[i].x) / len;
b[i] = Point(p, q);
if (a[i].x > b[i].x) {
swap(a[i], b[i]);
}
l[i] = Line(a[i], b[i], i);
eve[i - 1 << 1] = mp(a[i].x, i), eve[i - 1 << 1 | 1] = mp(b[i].x, -i);
}
sort(eve, eve + (n << 1));
for (int i = 0; i < n << 1; ++i) {
if (!i || abs(eve[i].X - x[m - 1]) > eps) {
x[m] = eve[i].X;
if (m) {
v[m - 1] = 0;
if (!s.empty()) {
v[m - 1] += s.begin()->S();
}
if (!t.empty()) {
v[m - 1] += t.begin()->S();
}
}
m++;
}
if (eve[i].Y > 0) {
int p = eve[i].Y;
if (a[p].y > 0) {
s.insert(l[p]);
} else {
t.insert(l[p]);
}
} else {
int p = -eve[i].Y;
if (a[p].y > 0) {
s.erase(l[p]);
} else {
t.erase(l[p]);
}
}
}
LD cur;
cur = 0;
for (int i = 0, j = 0; i < m; ++i) {
for (; j + 1 < m && x[j + 1] < x[i] + all; ++j) {
cur += (x[j + 1] - x[j]) * v[j];
}
CheckMax(ans, cur + (x[i] + all - x[j]) * (j == m - 1 ? 0 : v[j]));
cur -= (x[i + 1] - x[i]) * v[i];
}
cur = 0;
for (int i = m - 1, j = m - 1; ~i; --i) {
for (; j && x[j - 1] > x[i] - all; --j) {
cur += (x[j] - x[j - 1]) * v[j - 1];
}
CheckMax(ans, cur + (x[j] + all - x[i]) * (!j ? 0 : v[j - 1]));
if (i) {
cur -= (x[i] - x[i - 1]) * v[i - 1];
}
}
printf("%.9Lf\n", ans);
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
战略游戏
建出圆方树,询问就是问虚树上圆点个数。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 200005;
const int M = 20;
int n, m, q, ans, cnt, tim, top, dep[N], dfn[N], low[N], seq[N], siz[N], sta[N], sum[N], f[M][N];
vector <int> adj[N], adv[N];
inline void DFS(int x, int p) {
dfn[x] = low[x] = ++tim, sta[++top] = x;
bool f = false;
for (auto y : adj[x]) {
if (y != p || f) {
if (!dfn[y]) {
DFS(y, x), CheckMin(low[x], low[y]);
if (dfn[x] <= low[y]) {
++m, adv[x].pb(m);
for (int k = 0; k != y; adv[m].pb(k = sta[top--]));
}
} else {
CheckMin(low[x], dfn[y]);
}
} else {
f = true;
}
}
}
inline void DFS(int x) {
dfn[x] = ++tim, siz[x] = 1, sum[x] = sum[f[0][x]] + (x <= n);
for (int i = 1; i < M; ++i) {
f[i][x] = f[i - 1][f[i - 1][x]];
}
for (auto y : adv[x]) {
dep[y] = dep[x] + 1, f[0][y] = x, DFS(y), siz[x] += siz[y];
}
}
inline int LCA(int x, int y) {
if (dep[x] < dep[y]) {
swap(x, y);
}
if (dep[x] > dep[y]) {
for (int i = 0; i < M; ++i) {
if (dep[x] - dep[y] >> i & 1) {
x = f[i][x];
}
}
}
if (x == y) {
return x;
}
for (int i = M - 1; ~i; --i) {
if (f[i][x] != f[i][y]) {
x = f[i][x], y = f[i][y];
}
}
return f[0][x];
}
int Main() {
Read(n), Read(m), tim = top = 0;
for (int i = 1, x, y; i <= m; ++i) {
Read(x), Read(y);
adj[x].pb(y), adj[y].pb(x);
}
m = n, DFS(1, 0), tim = 0, DFS(1);
for (Read(q); q; --q) {
Read(cnt), ans = -cnt;
for (int i = 1; i <= cnt; ++i) {
Read(seq[i]);
}
sort(seq + 1, seq + cnt + 1, [&](const int &x, const int &y) {
return dfn[x] < dfn[y];
});
for (int i = cnt; i > 1; --i) {
seq[++cnt] = LCA(seq[i], seq[i - 1]);
}
sort(seq + 1, seq + cnt + 1, [&](const int &x, const int &y) {
return dfn[x] < dfn[y];
});
cnt = unique(seq + 1, seq + cnt + 1) - seq - 1, top = 0;
for (int i = 1; i <= cnt; ++i) {
for (; top && !(dfn[sta[top]] <= dfn[seq[i]] && dfn[sta[top]] + siz[sta[top]] >= dfn[seq[i]] + siz[seq[i]]); --top);
if (top) {
ans += sum[f[0][seq[i]]] - sum[sta[top]];
}
sta[++top] = seq[i];
}
for (int i = 1; i <= cnt; ++i) {
if (seq[i] <= n) {
++ans;
}
}
printf("%d\n", ans);
}
for (int i = 1; i <= m; ++i) {
adj[i].clear(), adv[i].clear(), dfn[i] = 0;
}
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
反回文串
枚举串的周期 d d ,计算最短周期等于自身长度 的串的个数记为 f f ,不难发现 ,答案是 ∑d|nf(d)(d1+[dmod2=0]) ∑ d | n f ( d ) ( d 1 + [ d mod 2 = 0 ] ) 。计算 f f 的时候可以发现它是一个类似积性函数的东西,推一推就可以算了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 200000;
const int M = 20;
LL n, k, a[N], pri[N];
int m, cnt, mod, b[N];
inline int Rand() {
#ifdef wxh010910
return rand() << 15 | rand();
#else
return rand();
#endif
}
inline LL RandLL() {
return (LL)Rand() << 30 | Rand();
}
inline LL Qul(LL x, LL y, LL mod) {
return ((x * y - (LL)(((LD)x * y + 0.5) / mod) * mod) % mod + mod) % mod;
}
inline LL Qow(LL x, LL y, LL mod) {
LL r = 1;
for (; y; y >>= 1, x = Qul(x, x, mod)) {
if (y & 1) {
r = Qul(r, x, mod);
}
}
return r;
}
inline bool MillerRabin(LL n) {
if (n == 2) {
return true;
}
if (n < 2 || !(n & 1)) {
return false;
}
LL a, x, y, u = n - 1;
int t = 0;
for (; !(u & 1); u >>= 1, ++t);
for (int i = 0; i < 10; ++i) {
a = RandLL() % (n - 1) + 1, x = Qow(a, u, n);
for (int j = 0; j < t; ++j, x = y) {
if ((y = Qul(x, x, n)) == 1 && x != 1 && x != n - 1) {
return false;
}
}
if (x != 1) {
return false;
}
}
return true;
}
inline LL PollardRho(LL a, LL c) {
LL k = 2, x = RandLL() % a, y = x, p = 1;
for (LL i = 1; p == 1; ++i) {
x = (Qul(x, x, a) + c) % a, p = __gcd(abs(x - y), a);
if (i == k) {
y = x, k <<= 1;
}
}
return p;
}
inline void Divide(LL x) {
if (x == 1) {
return ;
}
if (MillerRabin(x)) {
pri[cnt++] = x;
return ;
}
LL p = x;
while (p >= x) {
p = PollardRho(x, RandLL() % (x - 1));
}
Divide(p), Divide(x / p);
}
inline int Qow(int x, LL y) {
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod) {
if (y & 1) {
r = 1LL * r * x % mod;
}
}
return r;
}
inline int DFS(int x, LL cur, int val) {
if (x == m) {
if (cur & 1) {
return 1LL * cur % mod * Qow(k, cur + 1 >> 1) % mod * val % mod;
} else {
return 1LL * (cur >> 1) % mod * Qow(k, cur >> 1) % mod * val % mod;
}
}
LL ans = 0, cof = 1LL * val * ((1 - a[x]) % mod + mod) % mod;
if (a[x] & 1) {
ans += DFS(x + 1, cur, cof);
}
for (int i = 1; i < b[x]; ++i) {
ans += DFS(x + 1, cur *= a[x], cof);
}
ans += DFS(x + 1, cur *= a[x], val);
return ans % mod;
}
int Main() {
Read(n), Read(k), Read(mod), k %= mod, cnt = 0, Divide(n);
sort(pri, pri + cnt), m = 0;
for (int i = 0; i < cnt; ++i) {
if (!i || pri[i] != pri[i - 1]) {
a[m++] = pri[i], b[m - 1] = 0;
}
++b[m - 1];
}
printf("%d\n", DFS(0, 1, 1));
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Day 2
原题识别
求出欧拉序,对于 ,我们在 (dfnx,dfny) ( d f n x , d f n y ) 和 (endx,endy) ( e n d x , e n d y ) 两处权值加上 ansx,y a n s x , y ,在 (dfnx,endy) ( d f n x , e n d y ) 和 (dfny,endx) ( d f n y , e n d x ) 处权值减去 ansx,y a n s x , y ,那么操作二就是询问一个子矩形的权值和。
考虑对每种颜色分别算贡献,将产生贡献的矩形暴力搞出来,然后离散化,然后暴力给全局打上标记即可。查询可以扫描线加树状数组解决。可以证明产生贡献的矩形个数期望是线性的。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 200005;
const int M = 2005;
struct Event {
int x, l, r, f;
Event(int x = 0, int l = 0, int r = 0, int f = 0):x(x), l(l), r(r), f(f) {}
bool operator < (const Event &b) const {
return x < b.x;
}
};
int n, m, t, cnt, a[N], s[N], p[N], q[N], dic[N], per[N], tag[M][M];
LL ans[N], bit[N], bitx[N], bity[N], bitxy[N];
vector <Event> eve, qry;
vector <int> adj[N];
uint SA, SB, SC;
inline uint Rand() {
SA ^= SA << 16, SA ^= SA >> 5, SA ^= SA << 1;
uint t = SA;
SA = SB, SB = SC, SC ^= t ^ SA;
return SC;
}
inline void DFS(int x) {
p[x] = ++t, s[t] = 1;
for (auto y : adj[x]) {
DFS(y);
}
q[x] = ++t, s[t] = -1;
}
inline void AddDic(int x) {
dic[++cnt] = p[x] - 1, dic[++cnt] = q[x];
for (auto y : adj[x]) {
dic[++cnt] = p[y] - 1, dic[++cnt] = q[y];
}
}
inline void AddTag(int xl, int xr, int yl, int yr, int f) {
xl = lower_bound(dic, dic + cnt + 1, xl - 1) - dic + 1;
yl = lower_bound(dic, dic + cnt + 1, yl - 1) - dic + 1;
xr = lower_bound(dic, dic + cnt + 1, xr) - dic + 1;
yr = lower_bound(dic, dic + cnt + 1, yr) - dic + 1;
tag[xl][yl] += f, tag[xr][yr] += f;
tag[xr][yl] -= f, tag[xl][yr] -= f;
}
inline void AddRec(int x) {
AddTag(1, n << 1, p[x], q[x], 1);
AddTag(p[x], q[x], 1, n << 1, 1);
for (auto y : adj[x]) {
AddTag(p[y], q[y], p[y], q[y], -2);
}
}
inline void Modify(int x, int y, int a) {
LL b = 1LL * a * s[x - 1], c = 1LL * a * s[y - 1], d = 1LL * a * s[x - 1] * s[y - 1];
for (int i = y; i <= n << 1; i += i & -i) {
bit[i] += a, bitx[i] += b, bity[i] += c, bitxy[i] += d;
}
}
inline LL Query(int x, int y) {
LL a = 0, b = 0, c = 0, d = 0;
for (int i = y; i; i -= i & -i) {
a += bit[i], b += bitx[i], c += bity[i], d += bitxy[i];
}
return a * s[x] * s[y] - b * s[y] - c * s[x] + d;
}
int Main() {
Read(n), Read(m), Read(SA), Read(SB), Read(SC);
eve.clear(), qry.clear(), t = 0;
for (int i = 1; i <= n; ++i) {
adj[i].clear(), per[i] = i;
}
for (int i = 2; i <= m; ++i) {
adj[i - 1].pb(i);
}
for (int i = m + 1; i <= n; ++i) {
adj[Rand() % (i - 1) + 1].pb(i);
}
for (int i = 1; i <= n; ++i) {
a[i] = Rand() % n + 1;
}
DFS(1);
for (int i = 1; i <= n << 1; ++i) {
bit[i] = bitx[i] = bity[i] = bitxy[i] = 0;
s[i] += s[i - 1];
}
sort(per + 1, per + n + 1, [&](const int &x, const int &y) {
return a[x] < a[y];
});
for (int i = 1, j = 1; i <= n; i = j) {
for (dic[0] = 0, dic[cnt = 1] = n << 1; j <= n && a[per[j]] == a[per[i]]; ++j);
for (int k = i; k < j; ++k) {
AddDic(per[k]);
}
sort(dic, dic + cnt + 1), cnt = unique(dic, dic + cnt + 1) - dic - 1;
for (int k = 1; k <= cnt; ++k) {
for (int l = 1; l <= cnt; ++l) {
tag[k][l] = 0;
}
}
for (int k = i; k < j; ++k) {
AddRec(per[k]);
}
for (int k = 1; k <= cnt; ++k) {
for (int l = 1; l <= cnt; ++l) {
tag[k][l] += tag[k - 1][l] + tag[k][l - 1] - tag[k - 1][l - 1];
if (tag[k][l]) {
eve.pb(Event(dic[k - 1] + 1, dic[l - 1] + 1, dic[l], 1));
eve.pb(Event(dic[k] + 1, dic[l - 1] + 1, dic[l], -1));
}
}
}
}
Read(m);
for (int i = 1, o, x, y, xl, xr, yl, yr; i <= m; ++i) {
Read(o), Read(x), Read(y), ans[i] = 0;
if (o == 1) {
xl = xr = p[x], yl = yr = p[y];
} else {
xl = 1, xr = p[x], yl = 1, yr = p[y];
}
qry.pb(Event(xl - 1, yl, yr, -i));
qry.pb(Event(xr, yl, yr, i));
}
sort(eve.begin(), eve.end());
sort(qry.begin(), qry.end());
for (int i = 0, j = 0; i < eve.size() || j < qry.size(); ) {
if (i < eve.size() && (j == qry.size() || eve[i].x <= qry[j].x)) {
Modify(eve[i].x, eve[i].l, eve[i].f);
Modify(eve[i].x, eve[i].r + 1, -eve[i].f);
++i;
} else {
if (qry[j].f > 0) {
ans[qry[j].f] += Query(qry[j].x, qry[j].r) - Query(qry[j].x, qry[j].l - 1);
} else {
ans[-qry[j].f] -= Query(qry[j].x, qry[j].r) - Query(qry[j].x, qry[j].l - 1);
}
++j;
}
}
for (int i = 1; i <= m; ++i) {
printf("%lld\n", ans[i]);
}
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
旧试题
根据rng_58恒等式,答案为 ∑i∑j∑k[gcd(i,j)=1][gcd(i,k)=1][gcd(j,k)=1]⌊Ai⌋⌊Bj⌋⌊Ck⌋ ∑ i ∑ j ∑ k [ gcd ( i , j ) = 1 ] [ gcd ( i , k ) = 1 ] [ gcd ( j , k ) = 1 ] ⌊ A i ⌋ ⌊ B j ⌋ ⌊ C k ⌋ 。
然后贴一下 蒜头的奖杯 代码就行了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 100005;
const int mod = 1e9 + 7;
int n, A, B, C, ans, tot, a[N], b[N], c[N], d[N], e[N], f[N], p[N], q[N], r[N], s[N], t[N], u[N], v[N], w[N], pri[N];
bool chk[N];
inline void F(int *a, int n) {
for (int i = 1; i <= n; ++i) {
for (int j = i + i; j <= n; j += i) {
a[j] = (a[j] - a[i] + mod) % mod;
}
}
}
inline void G(int *a, int n) {
for (int i = 1; pri[i] <= n; ++i) {
for (int j = n / pri[i]; j; --j) {
a[j] = (a[j] + a[j * pri[i]]) % mod;
}
}
}
inline void H(int *a, int n) {
for (int i = 1; pri[i] <= n; ++i) {
for (int j = 1; j * pri[i] <= n; ++j) {
a[j * pri[i]] = (a[j * pri[i]] + a[j]) % mod;
}
}
}
int Main() {
Read(A), Read(B), Read(C), n = max(max(A, B), C), ans = tot = 0;
for (int i = 2; i <= n; ++i) {
if (!chk[i]) {
pri[++tot] = i;
}
for (int j = 1; i * pri[j] <= n; ++j) {
chk[i * pri[j]] = true;
if (i % pri[j] == 0) {
break;
}
}
}
pri[tot + 1] = n + 1;
for (int i = 1; i <= n; ++i) {
a[i] = A / i, b[i] = B / i, c[i] = C / i, d[i] = e[i] = f[i] = i == 1;
}
G(c, n), F(e, n), F(f, n);
for (int i = 1; i <= n; ++i) {
int m = n / i;
for (int j = 1; j <= m; ++j) {
p[j] = e[i * j], q[j] = f[i * j], r[j] = c[i * j], s[j] = a[i * j], t[j] = b[i * j], w[j] = d[i * j];
}
F(w, m);
for (int x = 1; x * x <= m; ++x) {
for (int j = 1; j <= m; ++j) {
u[j] = v[j] = 0;
}
for (int j = x; j <= m; j += x) {
u[j] = s[j], v[j] = t[j];
}
G(u, m), G(v, m);
for (int j = 1; j <= m; ++j) {
u[j] = 1LL * u[j] * w[j] % mod, v[j] = 1LL * v[j] * w[j] % mod;
}
H(u, m), H(v, m);
for (int j = 1; j <= m; ++j) {
u[j] = 1LL * u[j] * t[j] % mod, v[j] = 1LL * v[j] * s[j] % mod;
}
for (int y = x; x * y <= m; ++y) {
if (__gcd(x, y) == 1) {
LL g = 0, h = 0;
for (int j = y; j <= m; j += y) {
g += u[j], h += v[j];
}
g %= mod, h %= mod;
ans = (1LL * p[x] * q[y] % mod * r[x * y] % mod * g + ans) % mod;
if (x != y) {
ans = (1LL * p[y] * q[x] % mod * r[x * y] % mod * h + ans) % mod;
}
}
}
}
}
printf("%d\n", ans);
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
荣誉称号
不难发现只有前 2k+1 2 k + 1 个值有用,然后暴力树形DP就行了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 2050;
const int M = 205;
const LL inf = 1LL << 60;
int n, m, k, p, A, B, cur, lim, dis[N];
LL sum[N], f[N][M], g[N][M];
uint SA, SB, SC;
inline uint Rand() {
SA ^= SA << 16, SA ^= SA >> 5, SA ^= SA << 1;
uint t = SA;
SA = SB, SB = SC, SC ^= t ^ SA;
return SC;
}
inline void Modify(int i, int x, int y) {
for (; i >> cur > lim; cur += k);
i >>= cur, x %= m;
sum[i] += y, g[i][0] += 1LL * (m - x) * y, g[i][x] -= m * y;
}
inline void DFS(int x) {
if (x << 1 > lim) {
for (int i = 0; i < m; ++i) {
f[x][i] = g[x][i];
}
return ;
}
for (int i = 0; i < m; ++i) {
f[x][i] = inf;
}
DFS(x << 1);
if ((x << 1 | 1) > lim || dis[x << 1] != dis[x << 1 | 1]) {
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
CheckMin(f[x][(i + j) % m], g[x][i] + f[x << 1][j]);
}
}
return ;
}
DFS(x << 1 | 1);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
CheckMin(f[x][(i + j) % m], g[x][i] + f[x << 1][j] + f[x << 1 | 1][j]);
}
}
}
int Main() {
Read(n), Read(k), Read(m), Read(p), Read(SA), Read(SB), Read(SC), Read(A), Read(B), ++k, cur = 0, lim = min((1 << k) - 1, n);
for (int i = 1; i <= lim; ++i) {
sum[i] = 0;
for (int j = 0; j < m; ++j) {
g[i][j] = 0;
}
}
for (int i = 1, x, y; i <= n; ++i) {
if (i <= p) {
Read(x), Read(y);
} else {
x = Rand() % A + 1, y = Rand() % B + 1;
}
Modify(i, x, y);
}
for (int i = 1; i <= lim; ++i) {
for (int j = 1; j < m; ++j) {
g[i][j] += g[i][j - 1];
}
for (int j = 1; j < m; ++j) {
g[i][j] += sum[i] * j;
}
}
for (int i = lim; i; --i) {
dis[i] = i << 1 <= lim ? dis[i << 1] + 1 : 1;
}
DFS(1);
printf("%lld\n", f[1][0]);
return 0;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
for (Read(T); T; --T) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}