【APIO2019】奇怪装置(模意义下循环节)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zxyoi_dreamer/article/details/102777011

传送门


原来APIO也有签到题

题解:

首先分析性质,整除同余问题里面有计数那最重要的肯定就是循环节。

考虑一下什么时候 t 1 t_1 t 2 t_2 形成的数对相同。

{ t 1 + t 1 B t 2 + t 2 B ( m o d A ) t 1 t 2 ( m o d B ) \left\{ \begin{aligned} t_1+\lfloor\frac{t_1}{B}\rfloor &\equiv&& t_2+\lfloor\frac{t_2}{B}\rfloor &\pmod A\\ t_1&\equiv&& t_2 &\pmod B \end{aligned} \right.

t 2 = t 1 + B x t_2=t_1+B\cdot x ,考虑第一个式子:

t 1 + t 1 B t 1 + B x + t 1 + B x B ( m o d A ) A x ( B + 1 ) \begin{aligned} t_1+\lfloor\frac{t_1}{B}\rfloor&\equiv t_1+B\cdot x+\lfloor\frac{t_1+B\cdot x}{B}\rfloor&\pmod A\\ A&\mid x(B+1)\\ \end{aligned}

其实很容易发现了 x x 的合法取值就是 A gcd ( A , B + 1 ) x \dfrac{A}{\gcd(A,B+1)}|x ,并且容易循环节就是 t t + B x t\rightarrow t+B\cdot x ,则最小循环节长度就是 A B gcd ( A , B + 1 ) \dfrac{AB}{\gcd(A,B+1)}

则中间的部分很容易转化成线段覆盖,直接按照左端点排个序然后覆盖就行了。

注意循环节长度可能炸long long ,直接和最大的右端点取一下min即可。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

namespace IO{
	inline char gc(){
		static cs int Rlen=4e7+7;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	template<typename T>
	inline T get(){
		char c;T num;
		while(!isdigit(c=gc()));num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
	inline int gi(){return get<int>();}
	inline ll gl(){return get<ll>();}
}
using namespace IO;

using std::cerr;
using std::cout;
using pii=std::pair<ll,ll>;
#define fi first
#define se second

int n;ll A,B,M;
std::vector<pii> vec;

signed main(){
#ifdef zxyoi
	freopen("machine.in","r",stdin);
#endif
	n=gi(),A=gl(),B=gl();
	M=std::min(1.*A/std::__gcd(A,B+1)*B,1e18+5);
	while(n--){
		ll l=gl(),r=gl();
		if(r-l+1>=M){
			cout<<M,exit(0);
		}if(r>=M)l%=M,r%=M;
		if(l<=r)vec.push_back(pii(l,r));
		else vec.push_back(pii(0,r)),vec.push_back(pii(l,M-1));
	}
	ll nl=0,nr=-1,ans=0;
	std::sort(vec.begin(),vec.end());
	for(auto &t:vec){
		if(t.fi<=nr)nr=std::max(nr,t.se);
		else ans+=nr-nl+1,nl=t.fi,nr=t.se;
	}ans+=nr-nl+1;cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/102777011