CF755D 数学规律法 解题报告
题目传送门
这道题怎么都是数据结构题解?那本蒟蒻就来一篇数学题解(貌似是本题唯一的线性做法)。
思路:
模拟赛上有一道十分相似的题目,但是一开始想到的是用数据结构维护每次插入一条线段之前查询有多少根线段与其相交,但是太蒻了不会打,所以只好思考数学解法。
注意到本题有两句特别关键的话:
- 任意三个对角线都不能在同一点相交;
与 互质。
第一句话保证了省去了许多需要讨论的情况,从而得出一个结论:
增加的截⾯数
新边与之前连的边的交点数 。(这里只算图形内的交点)
而第二句话告诉我们:每个点都会被连且仅会被连一次,这意味着不需要考虑重边的问题。
观察了一会儿样例,发现新截面数的增长很有规律:每次加的数
画图举例,假设
先画第一条线段:
这时分割为了
再画一条:
这时变成了
再画一条呢?
会发现这时出现了一个交点,那么增长量将变为
这时我猜测每过一圈
再画一条:
交点又增加了一个!那么我们上面的假设就被否决了!这时我们提出新的规律:每经过一圈,
但是很快我发现这个结论也是错的,当
那么经过一堆完善后,设现在分割的份数为
- 若当前连的边未跨过
号点, ; - 否则若当前连的边的较大的端点刚好为
, 并且 将在本次操作后的两次操作内逐渐增大 ; - 否则就只剩下较大的端点超过
的情况了,先 ,再 ,并且 将在本次操作后的一次操作内逐渐增大 。
还没结束,万一
实际上,我们不难发现连边是具有对称性的,所以若
代码没什么好讲的,就是根据结论模拟,时间复杂度
代码是直接由考场代码改过来的。
#include <set>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1000010;
typedef long long ll;
int T;
int n, k;
void solve() {
scanf("%d%d", &n, &k);
if(k > n / 2) k = n - k;
int x = k % n + 1, lasx = 1;
ll res = 0, base = 2;
int d = 1;
int flag = -1; // flag 表示还有几次操作后 d 会 +1,相当于一个延时标记
for(int i = 1; i < n; i++) {
printf("%lld " , base);
if(~flag) flag--;
if(!flag) d++, flag = -1;
if(x + k > n && flag == -1) {
if(i != n - 1) d++;
base += d;
flag = 1;
lasx = x, x = (x + k - 1) % n + 1;
}
else if(x + k == n) {
base += d;
d++;
flag = 2;
lasx = x, x = (x + k - 1) % n + 1;
}
else {
base += d;
lasx = x, x = (x + k - 1) % n + 1;
}
res ^= (ll)i * base;
}
printf("%lld\n", base);
}
int main() {
T = 1;
while(T--) {
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具