2019.08.04【NOIP提高组】模拟 A 组 比赛总结

题目

锻造 (forging)

(File IO): input:forging.in output:forging.out
Time Limits: 1500 ms
Memory Limits: 262144 KB

1.1 题目背景

勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打
于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现…自己连一个史莱姆都打不过了。
勇者的精灵路由器告诉勇者其实是他自己的武器不好,并把他指引到了锻造厂。

1.2题目描述

“欢迎啊,老朋友。”
一阵寒暄过后,厂长带他们参观了厂子四周,并给他们讲锻造的流程。
“我们这里的武器分成若干的等级,等级越高武器就越厉害,并且对每一等级的武器都有两种属性值 b 和 c,但是我们初始只能花 a 个金币来生产 1 把 0 级剑…”
“所以你们厂子怎么这么垃圾啊,不能一下子就造出来 999 级的武器吗?”勇者不耐烦的打断了厂长的话。
“别着急,还没开始讲锻造呢…那我们举例你手中有一把 x 级武器和一把 y 级武器 ( y = max ⁡ ( x − 1 , 0 ) y =\max(x − 1, 0) y=max(x1,0)),我们令锻造附加值 k = min ⁡ ( c x , b y ) k=\min(c_x,b_y) k=min(cx,by),则你有 k c x \frac{k}{c_x} cxk的概率将两把武器融合成一把 x + 1 x+1 x+1级的武器。”
“…但是,锻造不是一帆风顺的,你同样有 1 − k c x 1−\frac{k}{c_x} 1cxk 的概率将两把武器融合成一把 max ⁡ ( x − 1 , 0 ) \max(x − 1, 0) max(x1,0)级的武器…”
勇者听完后暗暗思忖,他知道厂长一定又想借此机会坑骗他的零花钱,于是求助这个村最聪明的智者——你,来告诉他,想要强化出一把 n 级的武器,其期望花费为多少?
由于勇者不精通高精度小数,所以你只需要将答案对 998244353 998244353 998244353( 7 × 17 × 2 23 + 1 7 ×17 × 2^{23} + 1 7×17×223+1,一个质数 ) 取模即可。

1.3 格式

1.3.1 输入格式

第一行两个整数 n, a,含义如题所示。
为了避免输入量过大,第二行五个整数 bx, by, cx, cy, p,按照下列代码
来生成 b 和 c 数组。

b[0]=by+1;c[0]=cy+1;
for(int i=1;i<n;i++){
	b[i]=((long long)b[i-1]*bx+by)%p+1;
	c[i]=((long long)c[i-1]*cx+cy)%p+1;
}

1.3.2 输出格式

输出一行一个整数,表示期望花费。

1.4 样例

样例输入

Sample Input1
0 6432
4602677 3944535 2618884 6368297 9477531

Sample Input2
1 3639650
6136976 5520115 2835750 9072363 9302097

Sample Input3
10 2
2 33 6 66 2333333

Sample Input4
200 5708788
0 0 0 0 1

样例输出

Sample Output1
6432

Sample Output2
150643649

Sample Output3
976750710

Sample Output4
696441597

1.5数据范围

测试点 n ≤ n\leq n 特殊性质
1 0 0 0 N / A N/A N/A
2 1 1 1 N / A N/A N/A
3 200 200 200
4 200 200 200 N / A N/A N/A
5 2000 2000 2000
6 2000 2000 2000 N / A N/A N/A
7 1 0 6 10^6 106
8 1 0 6 10^6 106 N / A N/A N/A
9 1 0 7 10^7 107
10 1 0 7 10^7 107 N / A N/A N/A

对于特殊性质处标示为“有”的数据满足 p = 1。
对于 100% 的数据, 0 ≤ a ≤ 1 0 7 0 ≤ a ≤ 10^7 0a107 , 0 ≤ b x , b y , c x , c y < p < 1 0 7 0 ≤ bx, by, cx, cy < p < 10^7 0bx,by,cx,cy<p<107 , 0 ≤ n ≤ 1 0 7 0 ≤ n ≤10^7 0n107


整除 (division)

(File IO): input:division.in output:division.out
Time Limits: 3000 ms
Memory Limits: 262144 KB

Description

整除符号为 |,d|n 在计算机语言中可被描述为 n%d == 0。
现有一算式 n ∣ x m − x n|x^m - x nxmx,给定 n,m,求 [1, n] 以内 x 解的个数。
解可能很大,输出取模 998244353。

Input

其中 n 的给定方式是由 c 个不超过 t 的质数的乘积给出的,c 和 t 的范围会在数据范围中给出。

第一行一个 id 表示这个数据点的标号。

多组数据,其中第二行一个整数 T 表示数据组数。对于每一组数据:

第一行两个整数 c 和 m。

第二行 c 个整数,这些整数都是质数,且两两不同,他们的乘积即为n。

由于你可以通过输入求出 n,输入不再给出。

Output

对于每组数据输出一行,表示解的个数。

Sample Input

0
1
2 3
2 3

Sample Output

6

Data Constraint

2019.08.04【NOIP提高组】模拟 A 组 比赛总结_第1张图片

Hint

另有两个样例,见下发文件。


欠钱 (money)

(File IO): input:money.in output:money.out
Time Limits: 1000 ms
Memory Limits: 524288 KB

3.1 题目描述

南极的企鹅王国大学中生活着 n 只企鹅,作为 21 世纪的优秀大学生,企鹅们积极响应“大众创业,万众创新”的号召,纷纷创业。但是创业需要资金,企鹅们最近手头比较紧,只能互相借钱。
企鹅的借钱行为是有规律可循的:每只企鹅只会借一次钱,并且只会从一只企鹅那里借钱。借钱关系中不存在环(即不存在类似“金企鹅欠银企鹅钱,银企鹅欠铜企鹅钱,铜企鹅欠金企鹅钱”这种情况)。
企鹅的还钱行为也是有规律可循的:每只企鹅一旦新获得了一笔钱,就会立刻用这笔钱尽可能偿还自己欠的债务,直到债务偿清或用光这笔钱。它只会使用新获得的这笔钱,至于以前它有没有钱、有多少钱,与还钱行为无关。
企鹅们经常会做美梦。在一只企鹅 A 的梦里,它梦见自己创业成功,一下子获得了 +∞ 元钱,于是(按照上文的还钱规则)它赶快把钱用来还债,接着拿到钱的那只企鹅也赶快把钱用来还债…如此往复,直到所有获得钱的企鹅都完成了还债操作。梦醒之后,它开心地把梦的内容告诉了另外一只企鹅 B,企鹅 B 听了,也很开心,于是它问道:在你的梦里,我获得了多少钱呢?(指 B 去还债之前手里的钱,包括后来用于还债的钱和还债后B 手里剩下的钱。)
梦毕竟是梦,对实际的欠债情况没有影响。

3.2格式

3.2.1输入格式

第一行两个整数 n 和 m,表示有 n 只企鹅,m 个操作。
接下来 m 行,有两种可能的格式:

  • 0 a b c:修改操作,企鹅 a 向企鹅 b 借了 c 元钱。
  • 1 a b:查询操作,询问假如 a 有了 +∞ 元钱,企鹅 b 会净收入多少钱。

本题强制在线,也就是说:对于每个操作输入的变量 a, b, c(如果没有c,那就只有 a, b)都不是实际的 a, b, c,想获得实际的 a, b, c 应当经过以下操作:

a = (a + lastans) % n + 1;
b = (b + lastans) % n + 1;
c = (c + lastans) % n + 1;

其中,lastans 是上一次询问的答案。如果没有上一次询问,lastans 为0。

3.2.2输出格式

对每个询问操作,输出一行一个数表示答案。

3.3样例

3.3.1样例输入

5 9
0 1 2 1
0 0 1 2
1 0 1
1 2 4
0 2 1 1
1 2 0
0 3 1 0
1 4 2
1 3 4

3.3.2样例输出

3
2
0
1
0

3.4 数据范围

数据分为以下几种:
第一种:占 10%,n ≤ 5000 且 m ≤ 10000;
第二种:占 20%,所有借钱事件(0 开头的操作)发生在所有询问事件(1 开头的操作)之前;
第三种:占 30%,对于一只企鹅 A,最多只有一只企鹅向 A 借钱;
第四种:占 40%,没有特殊性质,n、m 大小有一定梯度。
对于所有数据,满足: n ≤ 1 0 5 , m ≤ 1 0 6 , 0 ≤ a , b , c ≤ n n ≤ 10^5 ,m ≤ 10^6 ,0 ≤ a, b, c ≤ n n105,m106,0a,b,cn a ≠ b a \neq b a̸=b


总结

今天的题目真是神仙~。
比赛时看了每一道题,感觉T3最可做。

  • 我用了一个并查集维护每一个点属于哪一个集合,如果加入一条x到y的边,那么把x的集合并入y的集合。
  • 查询的时候路径压缩一下,对于每一个在此过程中经过的点,都更新一下倍增数组和深度。 此时对于一组询问(x,y),如果x可以影响到y,那么x到y的路径一定是一条,因此我们只要从x开始往 d e p t h y depth_y depthy的深度跳。
  • 最后如果x走到 d e p t h y depth_y depthy的深度都不与y重合,输出0;否则答案就是一路上的边权最小值。

这个方法看起来可以AC,但是我并没有对此抱有太大信心,因为旁边的张JJ大佬一直在自言自语:“T3是Link Cut Tree。”但是我并没有举出范例,于是就这么打了。

打完T3后,我转眼看向T1、T2。T1我设 f i f_i fi表示锻造出 i 级武器的期望花费,结果发现锻造失败的情况会无限循环 虽然一个勇者的运气不会那么背,不然早就被史莱姆KO了 ,手足无措。最后只处理了n=0的情况,10分。

T2化出了一条 x m − 2 ≡ x − 1 ( m o d    n ) x^{m-2}\equiv x^{-1}\quad(\mod n) xm2x1(modn)的式子费马小定理?,搞了半天都不知道这是什么蘑菇,于是放弃,打暴力。

最后得分:10+20+30=60 好整齐啊


题解

T3

T3怎么没有100?神奇的是,我似乎通过了前30%的数据点!
我于是想了一个午饭的时间,发现 吃饭时思考效率明显提高 这样做并不能更新所有倍增时走到的点,那么甚至连depth数组都不满足单调性,还倍增个什么!

于是我沮丧地点开了题解,发现了三个字母:LCT。然后我就更加沮丧了
原来LCT只是一种解法,还有一种解法,很像我的水法。

  • 我们可以用倍增求出链上的最小值,关键在于怎么维护倍增数组。
  • 可以开一个无向无根树,每一次加边的时候就把两棵树启发式合并,就是把节点数少的那一棵接到节点数多的那一棵树上。接着暴力修改节点数少的那一棵树上的所有节点,修改它们的倍增数组和深度。时间复杂度 O ( n log ⁡ 2 2 n ) O(n\log_2^2n) O(nlog22n)
  • 那么怎么查询呢?在树上我们还维护一个记录方向的倍增数组,如果一条链上所有点都是从儿子到父亲,那么方向为2;如果是父亲到儿子,方向为1;如果两者都有,就为3( 3 = 1 ∣ 2 3=1|2 3=12
  • 最后把查询的两个点求lca,如果经过的链方向不对,那么输出0。
  • 时间复杂度 O ( n log ⁡ 2 2 n + m log ⁡ 2 n ) O(n\log_2^2n+m\log_2n) O(nlog22n+mlog2n)

T1

T1并没有我想象中的那么难,还是设 f i f_i fi表示锻造出 i 级武器的期望花费。如果锻造失败,就会得到一个 max ⁡ ( i − 2 , 0 ) \max(i-2,0) max(i2,0)级的武器,那么我们在重新锻造一把 i 级武器时就不用 max ⁡ ( i − 2 , 0 ) \max(i-2,0) max(i2,0)级的武器了。
于是可以列出状态转移方程(令 p = min ⁡ ( c i − 1 , b max ⁡ ( i − 2 , 0 ) ) c i − 1 p=\cfrac{\min\left(c_{i-1},b_{\max(i-2,0)}\right)}{c_{i-1}} p=ci1min(ci1,bmax(i2,0))):
f i = f i − 1 + f max ⁡ ( i − 2 , 0 ) + ( 1 − p ) ( f i − f max ⁡ ( i − 2 , 0 ) ) f i = f i − 1 + f max ⁡ ( i − 2 , 0 ) + f i − f max ⁡ ( i − 2 , 0 ) − p ⋅ f i + p ⋅ f max ⁡ ( i − 2 , 0 ) p ⋅ f i = f i − 1 + p ⋅ f max ⁡ ( i − 2 , 0 ) f i = f i − 1 p + f max ⁡ ( i − 2 , 0 ) f i = f i − 1 ⋅ c i − 1 ⋅ min ⁡ ( c i − 1 , b max ⁡ ( i − 2 , 0 ) ) − 1 + f max ⁡ ( i − 2 , 0 ) \begin{aligned} f_i&=f_{i-1}+f_{\max(i-2,0)}+(1-p)(f_i-f_{\max(i-2,0)})\\ f_i&=f_{i-1}+f_{\max(i-2,0)}+f_i-f_{\max(i-2,0)}-p\cdot f_i+p\cdot f_{\max(i-2,0)}\\ p\cdot f_i&=f_{i-1}+p\cdot f_{\max(i-2,0)}\\ f_i&=\frac{f_{i-1}}{p}+f_{\max(i-2,0)}\\ f_i&=f_{i-1}\cdot c_{i-1}\cdot \min\left(c_{i-1},b_{\max(i-2,0)}\right)^{-1}+f_{\max(i-2,0)} \end{aligned} fifipfififi=fi1+fmax(i2,0)+(1p)(fifmax(i2,0))=fi1+fmax(i2,0)+fifmax(i2,0)pfi+pfmax(i2,0)=fi1+pfmax(i2,0)=pfi1+fmax(i2,0)=fi1ci1min(ci1,bmax(i2,0))1+fmax(i2,0)
那么为什么不用把 f i − 1 + f max ⁡ ( i − 2 , 0 ) f_{i-1}+f_{\max(i-2,0)} fi1+fmax(i2,0)乘上p呢?第二天我吃早餐的时候想明白了,说明吃饭时思考效率明显提高 因为无论成功与否,我们都要用 i − 1 i-1 i1级和 max ⁡ ( i − 2 , 0 ) \max(i-2,0) max(i2,0)级的两把武器,只是失败后还要额外浪费一把 i − 1 i-1 i1级。

然后就可以轻松地AC了懵逼地TLE了。
以下是各种玄学优化:

  • 优化0:Pascal改用C++
  • 优化1:O(n)求1~p+1的逆元
inv[1]=1;
for(i=2;i<=p+1;i++) inv[i]=1LL*inv[mod%i]*(mod-mod/i)%mod;
  • i − 1 = ( P m o d    i ) − 1 ( P − ⌊ P i ⌋ ) m o d    P ( m o d    P ) i^{-1}=(P\mod i)^{-1}(P-\left\lfloor\frac{P}{i}\right\rfloor)\mod P\quad(\mod P) i1=(Pmodi)1(PiP)modP(modP)
    • 证明:https://blog.csdn.net/liyizhixl/article/details/78426576
  • 优化2:读入优化(不要用输出优化,没用的)
  • 优化3:把b,c,f数组都改成滚动数组
  • 优化4:卡常头文件
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"

T2

由于题目已经给出了 n = p 1 ⋅ p 2 ⋅ p 3 ⋯ p c n=p_1\cdot p_2\cdot p_3\cdots p_c n=p1p2p3pc n ∣ x m − x n|x^m-x nxmx,所以 p i ∣ x m − x ( i ∈ [ 1 , c ] , x ∈ [ 1.. n ] ) p_i|x^m-x(i\in[1,c],x\in[1..n]) pixmx(i[1,c],x[1..n])
显然答案就是每个这样的同余方程的解的数量+1的乘积。
于是就可以暴力了。
但是暴力又要卡常。。。十分麻烦。
我好不容易AC后,发现了一种清爽的求法: a n s = ∏ i = 1 c g c d ( p i − 1 , m − 1 ) + 1 ans=\prod_{i=1}^cgcd(p_i-1,m-1)+1 ans=i=1cgcd(pi1,m1)+1
证明在此:https://www.cnblogs.com/ImagineC/p/9880891.html

总结:这次比赛反映了我对期望等数学知识的不熟悉,应加强!


CODE

T1

#include
using namespace std;
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#define mod 998244353
#define N 10000005
int f[2],b[2],c[2],inv[N];
inline int min(int x,int y){return x<y?x:y;}
int main()
{
	freopen("forging.in","r",stdin);
	freopen("forging.out","w",stdout);
	register int n,a,bx,by,cx,cy,p,i,i_1=0,i_2=1;
	scanf("%d%d%d%d%d%d%d",&n,&a,&bx,&by,&cx,&cy,&p);
	b[0]=by+1,c[0]=cy+1,f[0]=a,inv[1]=1;
	for(i=2;i<=p+1;i++) inv[i]=1LL*inv[mod%i]*(mod-mod/i)%mod;
	for(i=1;i<=n;i++,i_1^=1,i_2^=1)
	{
		f[i_2]=(f[i<2?i_1:i_2]+1LL*f[i_1]*c[i_1]%mod*inv[min(c[i_1],b[i<2?i_1:i_2])])%mod;
		b[i_2]=(1LL*b[i_1]*bx%p+by)%p+1;
		c[i_2]=(1LL*c[i_1]*cx%p+cy)%p+1;
	}
	printf("%d\n",f[i_1]);
	return 0;
}

T2

暴力

#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#include
using namespace std;
#define mod 998244353
#define N 10005
int prime[N],pow[N],fac[N][2],m,id;
bool b[N];char buf[500005],ch;
inline char gc()
{
	static char *p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,500005,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
	while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
	while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline int power(int x,int P)
{
	int s=1,y=m;
	while(y)
	{
		if(y&1) s=s*x%P;
		x=x*x%P,y>>=1;
	}
	return s;
}
int main()
{
	freopen("division.in","r",stdin);
	freopen("division.out","w",stdout);
	register int i,j,t,num,p,ans,cnt;
	read(id),read(t);
	for(i=2;i<N;i++)
	{
		if(!b[i]) prime[++prime[0]]=i;
		for(j=1;j<=prime[0];j++)
		{
			if(i*prime[j]>=N) break;
			b[i*prime[j]]=1;
			fac[i*prime[j]][0]=prime[j],
			fac[i*prime[j]][1]=i;
			if(i%prime[j]==0) break;
		}
	}
	while(t--)
	{
		read(num),read(m);
		for(i=ans=1;i<=num;i++)
		{
			read(p);
			for(j=cnt=1;j<=p;j++)
			{
				if(b[j])
					pow[j]=pow[fac[j][0]]*pow[fac[j][1]]%p;
				else pow[j]=power(j,p);
				if(pow[j]==j) cnt++;
			}
			ans=1LL*ans*cnt%mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}

神奇方法

#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#include
using namespace std;
#define mod 998244353
#define N 10005
char ch;
inline char gc()
{
	static char buf[500005],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,500005,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
	while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
	while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline long long gcd(int x,int y)
{
	int r;
	while(y)
		r=x%y,x=y,y=r;
	return x+1;
}
int main()
{
	freopen("division.in","r",stdin);
	freopen("division.out","w",stdout);
	register int m,id,t,num,p,ans;
	read(id),read(t);
	while(t--)
	{
		read(num),read(m),ans=1;
		while(num--)
			read(p),ans=1LL*ans*gcd(p-1,m-1)%mod;
		printf("%d\n",ans);
	}
	return 0;
}

T3

#include
using namespace std;
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#define swap(x,y) x^=y,y^=x,x^=y
#define N 100005
struct edge{int end,len,dir,nex;}a[N<<1];//1:x->y 2:y->x
int fa[N],dep[N],siz[N],fir[N],f[N][17],min[N][17],dir[N][17],n,m,ans,cnt;
char ch;//1:son->father 2:father->son
inline char gc()
{
	static char buf[1000005],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000005,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
	while(ch=gc(),ch<'0'||ch>'9');x=ch-'0';
	while(ch=gc(),ch>='0'&&ch<='9') x=x*10+ch-'0';
}
inline int mymin(int x,int y){return x<y?x:y;}
inline void inc(int x,int y,int z)
{
	a[++cnt]=(edge){y,z,1,fir[x]},fir[x]=cnt;
	a[++cnt]=(edge){x,z,2,fir[y]},fir[y]=cnt;
}
void dfs(int k,int from,int num)
{
	fa[k]=num,dep[k]=dep[from]+1;
	for(int i=1;i<17;i++)
	{
		f[k][i]=f[f[k][i-1]][i-1];
		min[k][i]=mymin(min[k][i-1],min[f[k][i-1]][i-1]);
		dir[k][i]=dir[k][i-1]|dir[f[k][i-1]][i-1];
	}
	for(int i=fir[k];i;i=a[i].nex)
		if(a[i].end!=from)
		{
			f[a[i].end][0]=k;
			min[a[i].end][0]=a[i].len;
			dir[a[i].end][0]=a[i].dir^3;
			dfs(a[i].end,k,num);
		}
}
inline void add(int x,int y,int z)
{
	inc(x,y,z);
	if(siz[fa[x]]>siz[fa[y]]) swap(x,y);
	f[x][0]=y,min[x][0]=z,dir[x][0]=a[fir[x]].dir;
	siz[fa[y]]+=siz[fa[x]];
	dfs(x,y,fa[y]);
}
inline int qry(int u,int v)
{
	if(fa[u]!=fa[v]) return 0;
	int i,res=n,d=3;
	if(dep[u]>dep[v]) swap(u,v),d=0;
	for(i=16;i>=0;i--)
		if(dep[f[v][i]]>=dep[u])
		{
			if(dir[v][i]!=(1^d)) return 0;
			res=mymin(res,min[v][i]),v=f[v][i];
		}
	if(u==v) return res;
	for(i=16;i>=0;i--)
		if(f[v][i]!=f[u][i])
		{
			if(dir[v][i]!=(1^d)||dir[u][i]!=(2^d)) return 0;
			res=mymin(res,mymin(min[v][i],min[u][i]));
			v=f[v][i],u=f[u][i];
		}
	if(dir[v][0]!=(1^d)||dir[u][0]!=(2^d)) return 0;
	return mymin(res,mymin(min[v][0],min[u][0]));
}
int main()
{
	freopen("money.in","r",stdin);
	freopen("money.out","w",stdout);
	int i,j,x,y,z;
	read(n),read(m);
	for(i=1;i<=n;i++) fa[i]=i,dep[i]=siz[i]=1;
	while(m--)
	{
		read(i),read(x),read(y);
		x=(x+ans)%n+1,y=(y+ans)%n+1;
		if(i) printf("%d\n",ans=qry(x,y));
		else read(z),z=(z+ans)%n+1,add(x,y,z);
	}
	return 0;
}

你可能感兴趣的:(动态规划,暴力,数论,比赛总结,图论)