C2

首先用并查集维护\(1\)的连通块,然后用另外一个并查集维护第\(i\)行中,第\(j\)列之后的第一个\(0\)的位置,就是如果当前位置是\(1\)那么它的父亲是它右边的格子,否则是它自己。

时间复杂度\(O(nm\log m+nq)\)。

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
const int N = 1003, d[2][4] = {{0, 1, 0, -1}, {1, 0, -1, 0}};
int n, m, q, fa[N][N], cnt, Fa[N * N], Siz[N * N];
char str[N];
bool a[N][N];
inline int getfa(int x, int y){
return (fa[x][y] == y) ? y : (fa[x][y] = getfa(x, fa[x][y]));
}
inline int Getfa(int x){
return (Fa[x] == x) ? x : (Fa[x] = Getfa(Fa[x]));
}
inline int id(int x, int y){return (x - 1) * m + y;}
inline void work(int x, int y){
for(Rint i = 0;i < 4;i ++){
int nx = x + d[0][i], ny = y + d[1][i];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny]){
int fa1 = Getfa(id(x, y)), fa2 = Getfa(id(nx, ny));
if(fa1 != fa2){
if(Siz[fa1] > Siz[fa2]) swap(fa1, fa2);
Fa[fa1] = fa2; Siz[fa2] += Siz[fa1]; -- cnt;
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(Rint i = 1;i <= n * m;i ++) Fa[i] = i, Siz[i] = 1;
for(Rint i = 1;i <= n;i ++){
scanf("%s", str + 1);
for(Rint j = 1;j <= m;j ++){
a[i][j] = (str[j] == '1'); fa[i][j] = j + a[i][j]; cnt += a[i][j];
}
fa[i][m + 1] = m + 1;
}
for(Rint i = 1;i <= n;i ++)
for(Rint j = 1;j <= m;j ++)
if(a[i][j]) work(i, j);
scanf("%d", &q);
while(q --){
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
for(Rint i = x1;i <= x2;i ++){
int j = y1;
while((j = getfa(i, j)) <= y2){
++ cnt; a[i][j] = 1; fa[i][j] = j + 1;
work(i, j);
}
}
printf("%d\n", cnt);
}
}

D

首先甩上来一个单位根反演。

\[F_n=\frac{1}{2}((b+\sqrt a)^n+(b-\sqrt a)^n)
\]

于是你发现\(p\)不是质数,于是就自闭了。

然后你想起了BJ人民的扩域做法,就是搞一个域\(Z[\sqrt a]=\{x+y\sqrt a|x,y\in Z\}\),然后直接计算快速幂。但是你绝望地发现,最后有一个\(\frac{1}{2}\),于是你又废了。

然后你去看题解,发现逆向思维是非常重要的。平常大家都是递推公式\(\rightarrow\)通项公式,但是你有想到通项公式\(\rightarrow\)递推公式吗?

根据特征方程的理论,设\(F_n=AF_{n-1}+BF_{n-2}\),那么\(x^2-Ax-B=0\)的两根为\(b\pm \sqrt a\),所以\(A=b+\sqrt a+b-\sqrt a=2b\),\(B=-(b+\sqrt a)(b-\sqrt a)=a-b^2\)。然后用矩阵快速幂求出\(F_n\)就可以了。

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
int T;
LL a, b, p, n;
inline void upd(LL &a, LL b){a += b; if(a >= p) a -= p;}
struct Matrix {
LL x[2][2];
inline Matrix(){memset(x, 0, sizeof x);}
inline Matrix operator = (const Matrix &o){
memcpy(x, o.x, sizeof x);
return *this;
}
inline Matrix operator * (const Matrix &o) const {
Matrix res;
for(Rint i = 0;i < 2;i ++)
for(Rint k = 0;k < 2;k ++)
for(Rint j = 0;j < 2;j ++)
upd(res.x[i][j], (__int128) x[i][k] * o.x[k][j] % p);
return res;
}
} A, B;
inline Matrix kasumi(Matrix A, LL b){
Matrix res; res.x[0][0] = res.x[1][1] = 1;
while(b){
if(b & 1) res = res * A;
A = A * A; b >>= 1;
}
return res;
}
int main(){
scanf("%d", &T);
while(T --){
scanf("%lld%lld%lld%lld", &n, &a, &b, &p); a %= p; b %= p;
if(n == 0){puts("1"); continue;}
if(n == 1){printf("%lld\n", b); continue;}
A.x[0][0] = 2 * b % p; A.x[0][1] = (a + p - (__int128) b * b % p) % p;
A.x[1][0] = 1; B.x[0][0] = b; B.x[1][0] = 1;
B = kasumi(A, n - 1) * B;
printf("%lld\n", B.x[0][0]);
}
}

E

这是一个看上去很吓人的计算几何。

首先我们发现,这个范围实际上就是两个相距\(2d\)的平行线之间的部分,于是我们枚举其中一个平行线,发现它总能经过一个点,我们枚举这个点\(A\),看它在哪些时候可以覆盖另外一个点\(B\)。

分类讨论。

  1. \(dis(A,B)\le 2d\),设\(\alpha=\arctan\frac{y_B-y_A}{x_B-x_A}\),则直线倾角的范围是\([\alpha,\alpha+\pi]\)

  2. \(dis(A,B)>2d\),设\(\beta=\arcsin\frac{2d}{dis(A,B)}\),则直线倾角的范围是\([\alpha,\alpha+\beta]\cup[\alpha+\pi-\beta,\alpha+\pi]\)

如果看不懂的话,就来看个图。

于是问题就转化成了给出一堆区间,求一个点至多被覆盖多少次。这是一个经典题

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
const int N = 16003;
const double PI = acos(-1);
int n, d, x[N], y[N], ans, tag[N], len, tot;
double l[N], r[N], val[N];
inline void add(double x, double y){
if(x < 0 && y < 0) x += PI * 2, y += PI * 2;
if(x < 0){
l[++ tot] = x + 2 * PI; r[tot] = 2 * PI; val[++ len] = x + 2 * PI; val[++ len] = 2 * PI;
l[++ tot] = 0; r[tot] = y; val[++ len] = 0; val[++ len] = y;
} else {
l[++ tot] = x; r[tot] = y; val[++ len] = x; val[++ len] = y;
}
}
inline void work(int p){
len = tot = 0;
for(Rint i = 1;i <= n;i ++) if(i != p){
double alpha = atan2(y[i] - y[p], x[i] - x[p]), dis = (x[i] - x[p]) * (x[i] - x[p]) + (y[i] - y[p]) * (y[i] - y[p]);
if(dis <= d * d){
add(alpha, alpha + PI);
} else {
double beta = asin(1.0 * d / sqrt(dis));
add(alpha, alpha + beta); add(alpha + PI - beta, alpha + PI);
}
}
sort(val + 1, val + len + 1);
len = unique(val + 1, val + len + 1) - val - 1;
for(Rint i = 1;i <= tot;i ++){
int a = lower_bound(val + 1, val + len + 1, l[i]) - val, b = lower_bound(val + 1, val + len + 1, r[i]) - val + 1;
++ tag[a]; -- tag[b];
}
for(Rint i = 1;i <= len;i ++){
ans = max(ans, tag[i] += tag[i - 1]); tag[i - 1] = 0;
} tag[len] = 0;
}
int main(){
scanf("%d%d", &n, &d); d <<= 1;
for(Rint i = 1;i <= n;i ++) scanf("%d%d", x + i, y + i);
for(Rint i = 1;i <= n;i ++) work(i);
printf("%d", ans + 1);
}

Comet OJ Contest #13 简要题解的更多相关文章

  1. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  2. Comet OJ - Contest #2简要题解

    Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...

  3. Comet OJ - Contest #5 简要题解

    好久没更博了,还是象征性地更一次. 依然延续了简要题解的风格. 题目链接 https://cometoj.com/contest/46 题解 A. 迫真字符串 记 \(s_i\) 表示数字 \(i\) ...

  4. Comet OJ - Contest #13 「火鼠的皮衣 -不焦躁的内心-」

    来源:Comet OJ - Contest #13 芝士相关: 复平面在信息学奥赛中的应用[雾 其实是道 sb 题??? 发现原式貌似十分可二项式定理,然后发现确实如此 我们把 \(a^i\) 替换成 ...

  5. Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(hard)

    来源:Comet OJ - Contest #13 一眼并查集,然后发现这题 tmd 要卡常数的说卧槽... 发现这里又要用并查集跳过访问点,又要用并查集维护联通块,于是开俩并查集分别维护就好了 一开 ...

  6. 【题解】Comet OJ Round 70 简要题解

    [题解]Comet OJ Round 70 简要题解 A 将放在地上的书按照从小到大排序后,问题的本质就变成了合并两个序列使得字典序最小.可以直接模拟归并排序.直接用循环和std::merge实现这个 ...

  7. Comet OJ Contest #13 D

    Comet OJ Contest #13 D \(\displaystyle \sum_{i=0}^{\left\lfloor\frac{n}{2}\right\rfloor} a^{i} b^{n- ...

  8. Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(困难版) 并查集

    题意 给一个$ n \times m$ 的网格,每个格子里有一个数字,非 \(0\) 即 \(1\),行从上往下依次编号为 \(1, 2, \cdots, n\),列从左往右依次编号为 \(1, 2, ...

  9. Comet OJ - Contest #13

    Rank53. 第一次打这种比赛.还是有不少问题的,以后改吧. A题WA了两次罚了不少时. C写到一半发现只能过1,就先弃了. D一眼没看出来.第二眼看出来就是一个类似于复数的快速幂. 然后B切了. ...

随机推荐

  1. [高清·非影印] Python机器学习经典实例(电子书+源码)

    ------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...

  2. 启动Spring boot项目报错:java.lang.IllegalArgumentException: LoggerFactory is not a Logback

    java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on t ...

  3. Synchronized 与Lock的不同之处

    Synchronized 与Lock的不同之处 用法不一样.synchronized既可以加在方法上,也可以加载特定的代码块上,括号中表示需要锁的对象.而Lock需要显示地指定起始位置和终止位置.sy ...

  4. ADO.Net和SqlHelper封装

    1.什么是ADO.Net 简单来讲,ADO.NET是用于和数据源打交道的.Net结束,是一组向.NET程序员公开数据访问服务的类   2.ADO.NET的组成部分和对象模型 (1)ADO.NET的两个 ...

  5. SSM框架之MyBatis入门介绍

    一.什么是MyBatis? MyBatis源自Apache的iBatis开源项目, 从iBatis3.x开始正式更名为MyBatis.它是一个优秀的持久层框架. 二.为什么使用MyBatis? 为了和 ...

  6. ABAP开发环境终于支持以驼峰命名法自动格式化ABAP变量名了

    Jerry进入SAP成都研究院前,一直是用C/C++开发,所以刚接触ABAP,对于她在某些语法环境下大小写敏感,某些环境下不敏感的特性很不适应.那时候Jerry深深地怀念之前在C/C++编程时遵循的驼 ...

  7. 「8-27

    没有别的目的, 是最近发现一个小软件, 用起来感觉很不错, 所以想分享给大家. 首先这是一个 macOS 软件, 它的功能也很简单, 就是在菜单栏显示日期时间, 点按它可以显示日历, 没错, 简单到是 ...

  8. 加速 Unity 不同平台打包的一种思路

    Unity打包总的来说还不是一件特别复杂的事情, 但是我们知道任何关于跨平台(多线程等)这类问题, 总是会把事情搞得复杂起来. 以前项目的打包是通过Jenkins对一个工程下对不同平台多次打包, 不可 ...

  9. python3 queue队列

    一.queue队列 1.python3中的队列模块是queue,不是Queue 2.一般涉及到同步,多线程之类用到队列模块 3.定义了 queue.Queue 类,以及继承它的 queue.LifoQ ...

  10. P2756 飞行员配对方案问题[二分图最大匹配]

    题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员.在众多的飞行员中,每一名 ...