Replay

Problem A. I love cube
题目大意
T T T 组输入,每组一个整数 n n n.
求在 ( n − 1 ) 3 (n-1)^3 (n−1)3 的正方体中,存在多少个合法正三角形.
合法三角形:三角形的三个整顶点都在正方体内或正方体上,且三条边要至少平行于一个基平面.
1 ≤ T ≤ 1 0 5 , 1 ≤ n ≤ 1 0 18 1 \leq T \leq 10^5, 1 \leq n \leq 10^{18} 1≤T≤105,1≤n≤1018.
分析
XJ直接推了个柿子 A N S = 8 ∑ i = 1 n − 1 i 3 \begin{aligned} ANS = 8\sum_{i=1}^{n-1}{i^3} \end{aligned} ANS=8i=1∑n−1i3.
代码实现
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
typedef long long ll;
typedef unsigned long long ull;
const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
ll quick(ll a, ll b, ll p = mod)
{
ll s = 1;
while(b)
{
if(b & 1) s = s * a % p;
a = a * a % p;
b >>= 1;
}
return s;
}
ll inv(ll n, ll p = mod)
{
return quick(n, p - 2, p);
}
void work()
{
ll n; scanf("%lld", &n);
if(n == 1)
{
printf("0\n");
return;
}
--n;
n = n % mod;
ll ans = n * (n + 1) % mod * inv(2) % mod;
ans = ans * ans % mod;
ans = ans * 8 % mod;
printf("%lld\n", ans);
}
int main()
{
// cout << 5 * log2(inf) * (M + 2 * N) << "\n";
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// ios::sync_with_stdio(0);
// cin.tie(0); cout.tie(0);
int T; scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
// printf("Case #%d:\n", ca);
work();
}
// work();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
return 0;
}
Problem B. I love tree
题目大意
n n n 个点的树, q q q 次操作,每次操作分两种.
1 a b 1 \; a \; b 1ab 表示把从点 a a a 到 点 b b b 这条链上的点加二次函数 x 2 x^2 x2.
2 a 2 \; a 2a 表示查询点 a a a 的值.
1 ≤ n , q ≤ 1 0 5 , 1 ≤ a , b ≤ n 1 \leq n, q \leq 10^5, 1 \leq a, b \leq n 1≤n,q≤105,1≤a,b≤n.
分析
显然就是树链剖分 + 区间加二次函数.
因为中间的运算结果爆掉 ll,查了 n n n 久…
代码实现
#include <bits/stdc++.h>
using namespace std;
template <typename T>
void read(T& n)
{
n = 0; int f = 1; char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();}
while( isdigit(ch)) {
n = n * 10 + ch - '0', ch = getchar();}
n *= f;
}
template <typename T>
void print(T n)
{
if(n < 0) putchar('-'), n = -n;
if(n > 9) print(n / 10);
putchar(n % 10 + '0');
}
template <typename T>
void print(T n, char ch)
{
print(n), putchar(ch);
}
typedef __int128 ll;
const int M = (int)1e5;
namespace TA
{
struct TA
{
int n; ll tree[M + 5];
void init(int _n) {
n = _n; for(int i = 0; i <= n; ++i) tree[i] = 0;}
inline int lowbit(int n) {
return n&-n;}
void add(int a, ll b) {
for(int i = a; i <= n; i += lowbit(i)) tree[i] += b;}
ll ask(int r) {
ll s = 0; for(int i = r; i; i -= lowbit(i)) s += tree[i]; return s;}
} t[5];
void getUpdate(ll d[], ll b[], ll len)
{
d[0] = b[0] + b[1] + b[2];
d[1] = -2 * b[0] - b[1] + b[2];
d[2] = b[0];
d[3] = -b[0] - (len + 1) * b[1] - (len + 1) * (len + 1) * b[2];
d[4] = 2 * b[0] + (2 * len + 1) * b[1] + (2ll * len * len + 2 * len - 1) * b[2];
d[5] = -b[0] - len * b[1] - len * len * b[2];
}
void add(int l, int r, ll b[])
{
ll d[6]; getUpdate(d, b, r - l + 1);
ll p[6] = {
l, l + 1, l + 2, r + 1, r + 2, r + 3}, pw[6] = {
1, 1, 1, 1, 1, 1};
for(int j = 1; j < 5; ++j)
{
for(int k = 0; k < 6; ++k)
{
t[j].add(p[k], pw[k] * d[k]);
pw[k] *= p[k];
}
}
}
void getQuery(ll d[], ll r)
{
d[1] = r * r * r + 6 * r * r + 11 * r + 6;
d[2] = -(3 * r * r + 12 * r + 11);
d[3] = 3 * r + 6;
d[4] = -1;
}
ll ask(int r)
{
ll d[5], s = 0; getQuery(d, r);
for(int i = 1; i < 5; ++i) s += d[i] * t[i].ask(r);
s /= 6;
return (s + t[0].ask(r));
}
ll ask(int l, int r)
{
return ask(r) - ask(l - 1);
}
}
namespace

本文涵盖了多个算法和数据结构问题的解决方案,包括立方体内的正三角形计数、树链剖分、区间加二次函数、不同数字的异或和、字符串处理以及课程安排优化。每个问题都提供了详细的分析和高效代码实现,展示了如何运用数学和数据结构技巧来解决复杂问题。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



