AtCoder AGC031F Walk on Graph (图论、数论)

2024-02-15 15:32

本文主要是介绍AtCoder AGC031F Walk on Graph (图论、数论),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接

https://atcoder.jp/contests/agc031/tasks/agc031_f

题解

这题真是太神仙了……

首先我们转化一下问题,倒着来做,一开始有一个数\(0\), 每次走过一条边该数变为乘以\(2\)再加上这条边的边权。
我们用\((u,x)\)代表一个状态,表示当前在点\(u\),该数值为\(x\), \(x\)始终在\(\mod p\)意义下定义,\(p\)为模数。
假设\(u\)点有一条边连向\(v\)边权为\(w\), 则\((u,x)\)可以变成\((v,2x-w)\)(下用\(\Rightarrow\)表示),然后\((v,2x-w)\Rightarrow(u,4x-3w),(u,4x-3w)\Rightarrow(v,8x-7w),...\)
但是由于\(p\)是奇数,存在\(k>1\)使\(2^k\equiv 1(\mod p)\), 这个序列是循环的,由\((u,x)\)最终依然会到达\((u,x)\). 也就是说,我们可以认为这个递推关系是双向的,\((u,x)\Leftrightarrow (v,2x-w)\Leftrightarrow (u,4x-3w)\Leftrightarrow ...\)

这时,不要往\(2\)的幂的方向思考而一去不复返。考虑这个递推序列的前三步: \((u,x)\Leftrightarrow (u,4x-3w)\)
如果有两条连接的边分别是\(w_1,w_2\), 则\((u,x)\Leftrightarrow (u,4x-3w_1) \Leftrightarrow (u,4x-3w_2)\). 又因为\(4\)\(\mod p\)意义下有逆元,故\(4x\)可以代表任何数,即\((u,x)\Leftrightarrow (u,x\pm 3(w_1-w_2))\).
考虑一个点相连的那些边,由数论的基本知识可得,\((u,x)\Leftrightarrow (u,x+kt_u)\) (\(k\)为整数),其中\(t_u=\gcd(3g_u,p)\), \(g_u\)为与\(u\)相连所有边权的\(\gcd\). 即所有模\(t_u=\gcd(3g_u,p)\)同余的\(x\), \((u,x)\)的状态是一样的。
再进一步说,考虑不同的点,\((u,x)\Leftrightarrow (v,2x+w)\), \(u\)循环节为\(t_u\)导致\(v\)具有长度为\(2t_u\)的循环节,和其本身的取\(\gcd\)\(\gcd(t_u,2t_v)=\gcd(t_u,t_v)\) (\(2\)可以去掉是因为\(2\)\(3g_u\)互质因而与\(t_u\)互质)。由于整个图是联通的,这可以扩展到所有点,也就是对于所有\(u,x\)\((u,x)\Leftrightarrow (u,x+T)\), 其中\(T=\gcd^n_{u=1}t_u=\gcd(3\gcd^m_{i=1}w_i,p)\). 我们令\(G=\gcd^m_{i=1}w_i\). 显然\(T=G\)\(T=3G\).
整理一下,同一点所有模\(T\)同余的状态是一样的,而所有边权是模\(G\)同余的,且\(T=G\)\(T=3G\).
这样,我们可以把题目中的\(p\)直接改成\(T\), 不会对答案有任何影响。下面我们用\(p\)来代表\(T\).
注: 这里之所以我们只取了\((4x-3y)\)这一项而没有继续深入下去依然能得到正确的结论的原因是对任何\(k\in \mathbb{N}\), \((u,2^{2k}x+(2^{2k}-1)w)\), 而\(3|(2^{2k}-1)\).

既然所有边权是模\(G\)同余的,我们就可以设\(w_i=c_iG+z\), 其中\(0\le z\lt G\)是一个对于所有的边\(i\)都一样的数。
这个边权带常数\(z\)看上去很不优美,我们想办法把它消掉!我们把所有的当前数值\(x\)都增加\(z\), 并把所有的边权都减少\(z\). 改变后的值记为\(x'\), 那么现在的一次游走将会是: \(x'-z=x\rightarrow (2x+c_iG+z)=(2(x+z)+c_iG)-z=(2x'+c_iG)-z\), 也就是说\(x'\)经过一次操作会变成\(2x'+c_iG\), \(z\)的余数没了,其余操作没有变化!
于是我们执行把数值\(x\)增加\(z\)同时把边权减少\(z\)的操作,现在我们认为\(w_i=c_iG\),且询问的是\((t,z)\)\((s,z+r)\)是否可达。

因为\(w_i=c_iG\),故\((u,x)\Leftrightarrow (u,4x+3c_iG)\Leftrightarrow (u,4x)\), 且因为边权全部是\(G\)的倍数,在\(\mod 3G\)意义下只有\(3\)种取值,即可以认为\(c_i=0,1,2\). 那每个状态就可以表示成\((u,2^jx+kG)\)的形式,其中\(0\le j\lt 2,0\le k\lt 3\).
也就是说,对于每个点,我们只有\(6\)种状态有用!
然后的做法就很显然了,我们建出这\(6n\)个状态,对于每一条输入的边,操作权值之后把相应的状态用并查集缩起来。
对于询问,我们想要的是\((t,z)\)\((s,z+r)\)是否联通。枚举\(j\mod 2\)\(k\), 我们得到\(2^jz+kG\equiv z+r(\mod p)\). 我们需要判断是否存在\(j\)满足\(2^jz\equiv z+r-kG(\mod p)\), 这个对于每个\(j\)预处理一下\(2^jz\)记录下来奇偶即可。若存在且\((t,0,0)\)\((s,j,k)\)这两个状态联通,则答案是YES, 否则是NO.

时间复杂度\(O(6(n+m+q)\alpha(n)+p)\).

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
using namespace std;inline int read()
{int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f;
}const int N = 5e4;
const int mxP = 1e6;
struct AEdge
{int u,v,w;
} ae[N+3];
int uf[N*6+3];
bool ispw2[mxP+3][2];
int n,m,q,p,g;int gcd(int x,int y) {return y==0?x:gcd(y,x%y);}int getid(int x,int j,int k) {return (j*3+k)*n+x;}
int findfa(int u) {return u==uf[u]?u:uf[u]=findfa(uf[u]);}
void unionfa(int u,int v)
{int x = findfa(u),y = findfa(v);if(x!=y) {uf[x] = y;}
}int main()
{scanf("%d%d%d%d",&n,&m,&q,&p); g = p;for(int i=1; i<=n*6; i++) uf[i] = i;for(int i=1; i<=m; i++){scanf("%d%d%d",&ae[i].u,&ae[i].v,&ae[i].w);g = gcd(g,abs(ae[i].w-ae[1].w));}p = gcd(p,3*g);int z = ae[1].w%g;for(int i=1; i<=m; i++){int w = (ae[i].w-z)/g%3,u = ae[i].u,v = ae[i].v;for(int j=0; j<2; j++) for(int k=0; k<3; k++){unionfa(getid(u,j,k),getid(v,j^1,(k+k+w)%3));unionfa(getid(v,j,k),getid(u,j^1,(k+k+w)%3));}}for(int i=0,x=z; i<p; i++,x=(x<<1)%p) ispw2[x][i&1] = true;while(q--){int u,v,l; scanf("%d%d%d",&u,&v,&l); bool ans = false;for(int j=0; j<2; j++) for(int k=0; k<3; k++){int tmp = (z+l+(3-k)*g)%p;if(ispw2[tmp][j]){int uu = findfa(getid(v,0,0)),vv = findfa(getid(u,j,k));if(uu==vv) {ans = true; break;}}}if(ans==true) puts("YES"); else puts("NO");}return 0;
}

这篇关于AtCoder AGC031F Walk on Graph (图论、数论)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/711789

相关文章

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

图神经网络框架DGL实现Graph Attention Network (GAT)笔记

参考列表: [1]深入理解图注意力机制 [2]DGL官方学习教程一 ——基础操作&消息传递 [3]Cora数据集介绍+python读取 一、DGL实现GAT分类机器学习论文 程序摘自[1],该程序实现了利用图神经网络框架——DGL,实现图注意网络(GAT)。应用demo为对机器学习论文数据集——Cora,对论文所属类别进行分类。(下图摘自[3]) 1. 程序 Ubuntu:18.04

AtCoder Beginner Contest 370 Solution

A void solve() {int a, b;qr(a, b);if(a + b != 1) cout << "Invalid\n";else Yes(a);} B 模拟 void solve() {qr(n);int x = 1;FOR(i, n) FOR(j, i) qr(a[i][j]);FOR(i, n) x = x >= i ? a[x][i]: a[i][x];pr2(

SIGMOD-24概览Part7: Industry Session (Graph Data Management)

👇BG3: A Cost Effective and I/O Efficient Graph Database in ByteDance 🏛机构:字节 ➡️领域: Information systems → Data management systemsStorage management 📚摘要:介绍了字节新提出的ByteGraph 3.0(BG3)模型,用来处理大规模图结构数据 背景

【代码随想录训练营第42期 续Day52打卡 - 图论Part3 - 卡码网 103. 水流问题 104. 建造最大岛屿

目录 一、做题心得 二、题目与题解 题目一:卡码网 103. 水流问题 题目链接 题解:DFS 题目二:卡码网 104. 建造最大岛屿 题目链接 题解:DFS  三、小结 一、做题心得 也是成功补上昨天的打卡了。 这里继续图论章节,还是选择使用 DFS 来解决这类搜索问题(单纯因为我更熟悉 DFS 一点),今天补卡的是水流问题和岛屿问题。个人感觉这一章节题对于刚

2014年暑假培训 - 数论

A银河上的星星 /**************************************************************     Problem: 1014     User: DoubleQ     Language: C++     Result: Accepted     Time:190 ms     Memor