\(\text{T1}\)

很容易想到用 \(f_1 f_2 ... f_k\) 来表示第 \(n\) 项

发现重点关注指数即可,即我们要递推 \(f_1 ... f_k\) 对应的指数

递推涉及 \(K\) 项,不难想到矩阵加速递推,

弄一个 \(K \times K\) 的矩阵维护 \(fi\) 可以表示成 \(f_1 ... f_k\) 及对应指数

然后就结束了

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <cstring>
#define IN inline
typedef long long LL;
using namespace std; const int P = 998244353, phi = P - 1;
int n, K, f[205], b[205]; IN void Add(int &x, int y) {if ((x += y - phi) < 0) x += phi;} struct Matrix {
int n, m, a[205][205];
IN Matrix() {n = m = 0, memset(a, 0, sizeof a);}
IN Matrix operator * (const Matrix &b) {
Matrix c;
for(int i = 1; i <= n; i++)
for(int k = 1; k <= m; k++)
if (a[i][k])
for(int j = 1; j <= b.m; j++)
Add(c.a[i][j], (LL)a[i][k] * b.a[k][j] % phi);
c.n = n, c.m = b.m;
return c;
}
}I, A, B, Ans; IN void Init() {
I.n = I.m = K;
for(int i = 1; i <= K; i++) I.a[i][i] = 1;
A = I, B.n = B.m = K;
for(int i = 1; i < K; i++) B.a[i][i + 1] = 1;
for(int i = 1; i <= K; i++) B.a[K][i] = b[K - i + 1];
} IN Matrix M_pow(Matrix x, int y) {
Matrix c = I;
for(; y; x = x * x, y >>= 1) if (y & 1) c = c * x;
return c;
}
IN int fpow(int x, int y) {
int res = 1;
for(; y; x = (LL)x * x % P, y >>= 1) if (y & 1) res = (LL)res * x % P;
return res;
} int main() {
freopen("seq.in", "r", stdin);
freopen("seq.out", "w", stdout);
scanf("%d%d", &n, &K);
for(int i = 1; i <= K; i++) scanf("%d", &b[i]);
for(int i = 1; i <= K; i++) scanf("%d", &f[i]);
if (n <= K) {printf("%d\n", f[n]); return 0;}
Init(), Ans = A * M_pow(B, n - K);
LL ans = 1;
for(int i = 1; i <= K; i++) ans = ans * fpow(f[i], Ans.a[K][i]) % P;
printf("%lld\n", ans);
}

\(\text{T2}\)

最先有想法的题

一看,点双!圆方树!!

然后 \(dp\)

不过发现自己并不擅长在圆方树上的 \(dp\)

摸索半天。。。

总结下:

这题方点用来处理环等信息,起存储作用

而 \(dp\) 时为了方便圆点转移,并讨论情况,则需要

对于圆点,我们枚举其方点再枚举方点的儿子圆点

好处是提出了一个环,利于环上的转移

这题就是很好的案例

因为不知道这样做好转移,折腾半天。。。

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#include <vector>
#define IN inline
using namespace std; const int N = 2e4 + 5;
int n, m, tot, h[N], cnt, ans;
vector <int> g1[N], g2[N]; int dfn[N], low[N], stk[N], tp, dfc, bc[N], st[N], f[N], g[N];
void Tarjan(int x) {
dfn[x] = low[x] = ++dfc, stk[++tp] = x;
for(auto v : g1[x])
if (!dfn[v]) {
Tarjan(v), low[x] = min(low[x], low[v]);
if (dfn[x] == low[v]) {
++cnt, g2[x].emplace_back(cnt);
for(int u = 0; u ^ v; --tp) u = stk[tp], g2[cnt].emplace_back(u);
g[cnt] = g2[cnt].size() + 1;
if (g[cnt] <= 2) g[x] = 0;
}
}
else low[x] = min(low[x], dfn[v]);
} void dfs(int x, int fa) {
for(auto v : g2[x]) dfs(v, x), g[x] += g[v];
if (x > n && g2[x].size() == 1) g[x] = 0;
if (x <= n) {
for(auto v : g2[x]) {
int sum = 0, t = 1;
for(int i = 0; i < g2[v].size(); i++) {
f[x] = max(f[x], f[g2[v][i]] + sum + t + g[x] - g[v]);
sum += g[g2[v][i]], ++t;
}
sum = 0, t = 1;
for(int i = g2[v].size() - 1; i >= 0; i--) {
f[x] = max(f[x], f[g2[v][i]] + sum + t + g[x] - g[v]);
sum += g[g2[v][i]], ++t;
}
}
}
f[x] = max(f[x], g[x]);
} int main() {
scanf("%d%d", &n, &m);
for(int i = 1, x, y; i <= m; i++) scanf("%d%d", &x, &y), g1[x].emplace_back(y), g1[y].emplace_back(x);
cnt = n, Tarjan(1), dfs(1, 0), printf("%d\n", f[1]);
}

\(\text{T3}\)

非常显然的莫比乌斯反演,只是需要一条结论

\[\gcd(F_n,F_m) = F[\gcd(n,m)]
\]

然后就结束了

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define IN inline
using namespace std;
typedef long long LL; const int N = 55, M = 1e6, P = 1e9 + 9;
int a[N], n, pr[M], vis[M + 5], mu[M + 5], cnt, l, r, Mn; IN void Add(LL &x, LL y) {if ((x += y - P) < 0) x += P;} void Init() {
vis[1] = mu[1] = 1;
for(int i = 2; i <= M; i++) {
if (!vis[i]) pr[++cnt] = i, mu[i] = -1;
for(int j = 1; j <= cnt && pr[j] * i <= M; j++) {
vis[pr[j] * i] = 1;
if (!(i % pr[j])) break;
mu[pr[j] * i] = -mu[i];
}
}
for(int i = 2; i <= M; i++) mu[i] += mu[i - 1];
} IN int calc() {
int res = 1; r = Mn;
for(int i = 1; i <= n; i++)
res = (LL)res * (a[i] / l) % P, r = min(r, a[i] / (a[i] / l));
return res;
} int main() {
freopen("point.in", "r", stdin);
freopen("point.out", "w", stdout);
Init();
int T; scanf("%d", &T);
for(; T; --T) {
scanf("%d", &n);
Mn = M;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), Mn = min(Mn, a[i]);
LL ans = 0; int s;
for(l = 1; l <= Mn; l = r + 1)
s = calc(), Add(ans, (LL)(mu[r] - mu[l - 1] + P) * s % P);
Mn >>= 1;
for(int i = 1; i <= n; i++) a[i] >>= 1;
for(l = 1; l <= Mn; l = r + 1)
s = calc(), Add(ans, (LL)(mu[r] - mu[l - 1] + P) * s % P);
printf("%lld\n", ans);
}
}

\(\text{T4}\)

经典神题

需要发现一些性质

性质 \(1\):两个相交的优美区间相交部分一定是优美区间

用处是:考虑一个询问区间 \(l,r\),如果暴力枚举 \(R \ge r\)

找到 \(L <= l\) 且 \([L,R]\) 是优美区间

那么从小到大枚举 \(R\),第一个成功了的区间一定最短

性质 \(2\):借以判断优美区间

很容易想到区间 \([l,r]\) 若满足 \(Max-Min=r-l\) 则此区间为优美区间

然而我不会用

另一个角度,优美区间两数差为 \(1\) 的数对数量是 \(r-l\)

进而可以推出区间中两数差为 \(1\) 的数对数量为 \(n\),且区间长为 \(n+1\),那么这个区间为优美区间

很好想

这有什么用处?

从小到大枚举 \(R\),维护有哪些 \(L\) 使得 \([L,R]\) 为优美区间

当 \(R\) 增大,即新增一个数位右端点数,我们可以快速维护 \(L\)

即考虑包含 \(a[R]-1,a[R]+1\) 的区间,这些区间两数差为 \(1\) 的数对数量均可加 \(1\)

并且只需用这个条件就可判断优美区间了,线段树支持区间加

最短的话线段树上二分找到最右的 \(L\) 使得 \([L,R]\) 为优美区间即可

而发现一个询问可能要查询很多次而没有结果

优化是给询问排序,用堆维护当前 \(r \le R\) 的询问中 \(L\) 从大到小的顺序

当前 \(R\) 下,若这个询问失败,后面的询问必然失败,可以终止查询,以少做无用功

问号:这是原题 \(\text{P4747 [CERC2017]Intrinsic Interval}\)

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <queue>
#include <iostream>
#include <algorithm>
#define IN inline
using namespace std; const int N = 1e5 + 5;
int n, m, a[N], R, pos[N]; struct Que {
int l, r, id;
IN bool operator < (const Que &a) const {return r < a.r;}
}b[N];
struct node {
int l, id;
IN bool operator < (const node &a) const {return l < a.l;}
};
priority_queue <node> Q;
struct Rev {int l, r;}ans[N]; #define ls (p << 1)
#define rs (ls | 1)
int mx[N << 2], tag[N << 2]; IN void pushup(int p) {mx[p] = max(mx[ls], mx[rs]);}
IN void pushdown(int p) {
if (!tag[p]) return;
mx[ls] += tag[p], mx[rs] += tag[p], tag[ls] += tag[p], tag[rs] += tag[p];
tag[p] = 0;
} void Modify(int p, int l, int r, int x, int y, int v) {
if (x <= l && r <= y) return tag[p] += v, mx[p] += v, void();
pushdown(p);
int mid = l + r >> 1;
if (x <= mid) Modify(ls, l, mid, x, y, v);
if (y > mid) Modify(rs, mid + 1, r, x, y, v);
pushup(p);
} int Query(int p, int l, int r, int x) {
if (mx[p] < R) return 0;
if (l == r) return l;
pushdown(p);
int mid = l + r >> 1, res = 0;
if (x > mid && mx[rs] >= R) res = Query(rs, mid + 1, r, x);
if (res) return res;
if (mx[ls] >= R) res = Query(ls, l, mid, x);
return res;
} int main() {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), pos[a[i]] = i;
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d%d", &b[i].l, &b[i].r), b[i].id = i;
sort(b + 1, b + m + 1);
for(int i = 1, j = 1; i <= n; i++) {
R = i, Modify(1, 1, n, i, i, i);
if (a[i] > 1 && pos[a[i] - 1] <= i) Modify(1, 1, n, 1, pos[a[i] - 1], 1);
if (a[i] < n && pos[a[i] + 1] <= i) Modify(1, 1, n, 1, pos[a[i] + 1], 1);
while (j <= m && b[j].r <= i) Q.push(node{b[j].l, b[j].id}), ++j;
while (!Q.empty()) {
node now = Q.top();
int gd = Query(1, 1, n, now.l);
if (gd) ans[now.id] = Rev{gd, i}, Q.pop();
else break;
}
}
for(int i = 1; i <= m; i++) printf("%d %d\n", ans[i].l, ans[i].r);
}

JZOJ 2022.07.18【提高组A】模拟的更多相关文章

  1. 2018.12.30【NOIP提高组】模拟赛C组总结

    2018.12.30[NOIP提高组]模拟赛C组总结 今天成功回归开始做比赛 感觉十分良(zhōng)好(chà). 统计数字(count.pas/c/cpp) 字符串的展开(expand.pas/c ...

  2. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

  3. JZOJ 5184. 【NOIP2017提高组模拟6.29】Gift

    5184. [NOIP2017提高组模拟6.29]Gift (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed ...

  4. JZOJ 5185. 【NOIP2017提高组模拟6.30】tty's sequence

    5185. [NOIP2017提高组模拟6.30]tty's sequence (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB ...

  5. JZOJ 5196. 【NOIP2017提高组模拟7.3】B

    5196. [NOIP2017提高组模拟7.3]B Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  6. JZOJ 5197. 【NOIP2017提高组模拟7.3】C

    5197. [NOIP2017提高组模拟7.3]C Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  7. JZOJ 5195. 【NOIP2017提高组模拟7.3】A

    5195. [NOIP2017提高组模拟7.3]A Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  8. Vigenère密码 2012年NOIP全国联赛提高组(字符串模拟)

    P1079 Vigenère 密码 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简 ...

  9. 等价表达式 2005年NOIP全国联赛提高组(栈模拟)

    P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的 ...

  10. 2017.07.06【NOIP提高组】模拟赛B组

    Summary 今天比赛感觉题目很奇葩,都可以用许多简单方法来做,正确性都显然,当然也有点水,也就是说是考我们的数感和数学知识,而程序,只是代码的体现. 这次的时间安排感觉不错,因为很快就打完最后一道 ...

随机推荐

  1. 详解 Redis 中 big keys 发现和解决

    在使用 Redis 时,可能会出现请求响应慢.网络卡顿.数据丢失的情况.排查问题的时候,发现是 big keys 的问题. 什么是 big keys 在 Redis 中,一个字符串类型最大可以达到 5 ...

  2. 用 Java?试试国产轻量的 Solon v1.11.4(带视频)

    一个更现代感的 Java 应用开发框架:更快.更小.更自由.没有 Spring,没有 Servlet,没有 JavaEE:独立的轻量生态.主框架仅 0.1 MB. @Controller public ...

  3. python基础之hashilb模块、logging模块

    hashlib加密模块 1.何为加密 将文明数据处理成密文数据 让人无法看懂 2.为什么要加密 保证数据的安全,防止密码泄露 3.如何判断数据是否加密 密文数据的表现形式一般都是一串没有规则的字符串( ...

  4. 搭建漏洞环境及实战——搭建XSS测试平台

    XSS测试平台是测试XSS漏洞获取cookie并接收Web页面的平台,XSS可以做成JS能做的所有事,包括但不限于窃取cookie.后台增删文章.钓鱼.利用CSS漏洞进行传播.修改网页代码.网站重定向 ...

  5. git cherry-pick 同步修改到另一个分支

    我们在开发中有时会遇到,需要将另一个分支部分修改同步到当前分支. 如下图,想把 devA 分支中 commit E 和 F,同步到下面绿色的 devB 分支中. 这时候就可以使用 git cherry ...

  6. python 之路 37 Navicat 可视化软件使用、 pymysql模块使用

    多表查询的两种方法 方式1:连表操作 inner join 内连接 select * from emp inner join dep on emp.dep_id=dep.id; 只连接两张表中公有的数 ...

  7. 纸张尺寸【第十三届蓝桥杯省赛C++C组】

    纸张尺寸 在 ISO 国际标准中定义了 \(A0\) 纸张的大小为 \(1189mm×841mm\),将 \(A0\) 纸沿长边对折后为 \(A1\) 纸,大小为 \(841mm×594mm\) ,在 ...

  8. 蓝桥真题——最短路 & 门牌制作

    题目1 最短路 标签:填空题 2019 省赛 如下图所示,G 是一个无向图,其中蓝色边的长度是 1.橘色边的长度是 2.绿色边的长度是 3. 则从 A 到 S 的最短距离是多少? 答案 由图可得,最短 ...

  9. AI换脸实战教学(FaceSwap的使用)---------第二步Tools:处理输入数据集。

    续上篇:https://www.cnblogs.com/techs-wenzhe/p/12936809.html 第一步中已经提取出了源视频的人脸照片以及对应人脸遮罩(landmark以及其他自选遮罩 ...

  10. final关键字用于修饰成员方法-final关键字用于修饰局部变量

    final关键字用于修饰成员方法 修饰方法 格式如下: 修饰符 final 返回值类型 方法名(参数列表){ //方法体 } 重写被 final 修饰的方法,编译时就会报错. final关键字用于修饰 ...