题意:2t|k(k+1),求k的最小值
设2t=a*b , a|k,b|(k+1) ==> k=ax , k+1 = by
==>ax+1=by ==> a(-x)+by=1 <==> ax同余1(mod b)
2t分解质因数,二进制枚举即可,位数很少,记录小的x即可
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define freopne freopen("in.txt","r",stdin)
#define int long long
using namespace std;
const int N = 1e5+10;
map<int,int>mp;
vector<int>v;
int p[N];
int n;
int gcd(int a,int b){
return b ? gcd(b,a%b):a;
}
int lcm(int a,int b){
return a/gcd(a,b)*b;//先除在乘防溢出
}
int exgcd(int a,int b,int &x,int &y){//扩欧板子
if(!b){
x=1,y=0;
return a;
}
int d = exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
void work(int n){//分解质因数
for(int i=2;i<=n/i;i++){
if(n%i==0){
v.push_back(i);
mp[i]=1;
while(n%i==0){
mp[i]*=i;
n/=i;
}
}
}
if(n>1)mp[n]=n,v.push_back(n);
}
signed main(){
ios;
cin>>n;
for(int i=1;i<=n;i++)cin>>p[i];
int t = p[1];//不要一开始写两个数字,防止n只有1,WA的教训
for(int i=2;i<=n;i++)t=lcm(t,p[i]);//求最小公倍数
work(2*t);
// for(auto [a,b]:mp)cout<<a<<' '<<b<<'\n';
int res=8e18;
for(int i=0;i<(1ll<<v.size());i++){
int a=1;
for(int j=0;j<v.size();j++)
if((i>>j)&1)a*=mp[v[j]];
int b = 2*t/a;
int x,y,d=exgcd(a,b,x,y);
x=-x;
x = (x%b+b)%b;//把x转换成最小正数
if(a*x)res=min(res,a*x);
}
cout<<res;
return 0;
}