P5345 【XR-1】快乐肥宅

基础数论的集大成者。

题目简介

题目名称:【】快乐肥宅

题目来源:洛谷原创
评测链接:https://www.luogu.com.cn/problem/P5345

形式化题意:给定 ,第 秒会有 ,问最小时间使得

数据范围:

我们可以得到 个高次同余方程形如 ,从而解出 个不同的 ,不难发现, 会在一定数量后进入一个直观的循环,从而得到 个同余方程形如: ),这样就可以用 来进行合并,但由于 并没有被限制为质数,所以需要使用

AC Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// ----- Eternally question-----
// Problem: P5345 【XR-1】快乐肥宅
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5345
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// Written by: Eternity
// Time: 2023-01-15 19:15:32
// ----- Endless solution-------

#include<bits/stdc++.h>
#define re register
typedef long long ll;
template<class T>
inline void read(T &x)
{
x=0;
char ch=getchar(),t=0;
while(ch<'0'||ch>'9') t|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
if(t) x=-x;
}
template<class T,class ...T1>
inline void read(T &x,T1 &...x1){ read(x),read(x1...); }
template<class T>
inline void write(T x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
template<>
inline void write(bool x){ putchar(x?'1':'0'); }
template<>
inline void write(char c){ putchar(c); }
template<>
inline void write(char *s){ while(*s!='\0') putchar(*s++); }
template<>
inline void write(const char *s){ while(*s!='\0') putchar(*s++); }
template<class T,class ...T1>
inline void write(T x,T1 ...x1){ write(x),write(x1...); }
template<class T>
inline bool checkMax(T &x,T y){ return x<y?x=y,1:0; }
template<class T>
inline bool checkMin(T &x,T y){ return x>y?x=y,1:0; }
using Pir=std::pair<int,int>;
const int MAXN=1e3+10,MAXS=1e7+10;
const int INF=0x3f3f3f3f;
const int INFTY=1e9;
int N,K[MAXN],R[MAXN],G[MAXN];
int T[MAXN],D[MAXN];
int exgcd(int a,int b,int &x,int &y)
{
if(!b){ x=1,y=0;return a; }
int gcd=exgcd(b,a%b,y,x);
y-=a/b*x;return gcd;
}
inline int inv(int a,int p)
{
int x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
}
inline int qPow(int a,int b,int p)
{
int res=1;
while(b)
{
if(b&1) res=1ll*res*a%p;
a=1ll*a*a%p;b>>=1;
}
return res;
}
inline ll qMul(ll a,ll b,ll p)
{
ll res=0;
while(b)
{
if(b&1) res=(res+a)%p;
a=(a+a)%p;b>>=1;
}
return res;
}
inline int Bsgs(int a,int b,int p)
{
std::unordered_map<int,int>Hash;
int k=std::sqrt(p)+1;
int ay=1;
for(int y=0;y<k;++y,ay=(ll)ay*a%p) Hash[(ll)b*ay%p]=y;
int ak=qPow(a,k,p),at=qPow(a,k,p);
for(int t=1;t<=k;++t,ak=(ll)ak*at%p)
{
if(Hash.find(ak)==Hash.end()) continue;
int res=k*t-Hash[ak];
if(res>=0) return res;
}
return -1;
}
inline Pir exBsgs(int a,int b,int p)
{
if(p==1) return (Pir){0,1};
a%=p,b%=p;
int x,y;
int g=exgcd(a,p,x,y),f=1,k=0;
while(g>1)
{
if(b%g)
{
if(b==1) return (Pir){0,-1};
return (Pir){-1,-1};
}
++k,b/=g,p/=g;
f=(ll)f*(a/g)%p;
g=exgcd(a,p,x,y);
if(f==b)
{
if(g>1) return {k,-1};
int y=Bsgs(a,1,p);
return (Pir){k,y};
}
}
x=Bsgs(a,(ll)b*inv(f,p)%p,p);
if(x==-1) return (Pir){-1,-1};
y=Bsgs(a,1,p);
return (Pir){x%y+k,y};
}
ll A,B;
inline int merge(ll a,ll b)
{
int x,y;
ll gcd=exgcd(A,a,x,y),c=B-b;
if(c%gcd) return -1;
c/=gcd;
x=(x*c%a+a)%a;
ll lcm=A/gcd*a;
B=(B-A*x%lcm+lcm)%lcm;
A=lcm;
return 1;
}
inline int div_ceil(int a,int b)
{ return (a-1)/b+1;}
int Excrt(int n,int x)
{
A=D[1],B=T[1];
for(int i=2;i<=n;++i)
{
if(A>INFTY&&(B-T[i])%D[i]) return -1;
else if (A<=INFTY&&merge(D[i],T[i])==-1) return -1;
}
if(B<x) B+=div_ceil(x-B,A)*A;
if(B>INFTY) return -1;
return B;
}
int Mx,pos=-1;
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(N);
for(int i=1;i<=N;++i) read(K[i],G[i],R[i]);
for(int i=1;i<=N;++i)
{
auto res=exBsgs(K[i],R[i],G[i]);
T[i]=res.first,D[i]=res.second;
}
for(int i=1;i<=N;++i) if(T[i]==-1) return puts("Impossible"),0;
for(int i=1;i<=N;++i)
{
if(D[i]==-1)
{ pos=T[i];continue; }
checkMax(Mx,T[i]);
}
if(pos!=-1)
{
for(int i=1;i<=N;++i)
if((D[i]==-1&&pos!=T[i])||(D[i]!=-1&&(pos<T[i]||(pos-T[i])%D[i])))
{ puts("Impossible");return 0;}
write(pos);
return 0;
}
int ans=Excrt(N,Mx);
if(ans==-1) puts("Impossible");
else write(ans);
return 0;
}
/*

*/