Description&Data Constraint
1
≤
T
≤
100
,
1
≤
n
≤
1
0
12
1\le T\le100,1\le n \le 10^{12}
1≤T≤100,1≤n≤1012
Solution
简单来说,就是求满足 x ( x + 1 ) 2 % n = 0 \dfrac{x(x+1)}{2}\%n=0 2x(x+1)%n=0 的最小的 x x x 。
推导一下:
n ∣ x ( x + 1 ) 2 n|\dfrac{x(x+1)}{2} n∣2x(x+1)
2 n ∣ x ( x + 1 ) 2n|x(x+1) 2n∣x(x+1)
枚举 a ∣ 2 n a|2n a∣2n,令 b = 2 n a b=\frac{2n}{a} b=a2n
设 a p = x + 1 , b q = x ap=x+1,bq=x ap=x+1,bq=x,联立得到 a p − b q = 1 ap-bq=1 ap−bq=1。
要求 b q bq bq 的最小值,扩欧经典题。
有解满足 gcd ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1,因此只用判断 2 n 2n 2n 的每个质因数是否给 a a a,要么不给,要么全给。
时间复杂度 O ( 求质因数的时间 + 2 质因子个数 × log ) O(\text{求质因数的时间}+2^{\text{质因子个数}}\times \log) O(求质因数的时间+2质因子个数×log)
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define MX 500000
#define N 10000000
using namespace std;
int t,bz[MX];
ll n,num,ans,p[N],prime[MX];
void exgcd(ll a,ll b,ll &x,ll &y)
{
if (b==0)
{
x=1;
y=0;
return;
}
exgcd(b,a%b,x,y);
ll u=y,v=x-(a/b)*y;
x=u;
y=v;
}
void dg(ll k,ll x)
{
if (k>num)
{
ll y=n/x;
ll xx,yy;
exgcd(x,y,xx,yy);
xx=-xx;
if (xx<=0) xx+=y;
ans=min(ans,x*xx);
return;
}
dg(k+1,x);
dg(k+1,x*p[k]);
}
int main()
{
for (int i=2;i<=MX;++i)
{
if (!bz[i]) prime[++prime[0]]=i;
for (int j=1;j<=prime[0]&&i*prime[j]<=MX;++j)
{
bz[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
scanf("%d",&t);
while (t--)
{
ans=12345679887654321;
scanf("%lld",&n);
num=0;n*=2;
ll nn=n;
for (int i=1;i<=prime[0];++i)
{
if (nn%prime[i]==0)
{
p[++num]=1;
while (nn%prime[i]==0)
{
p[num]*=prime[i];
nn/=prime[i];
}
}
}
if (nn>1) p[++num]=nn;
dg(1,1);
printf("%lld\n",ans);
}
return 0;
}