jzoj7177质因数分解扩展欧几里得鱼跃龙门
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj7177质因数分解扩展欧几里得鱼跃龙门相关的知识,希望对你有一定的参考价值。
Comet OJ Contest #10 C 鱼跃龙门 Cold_Chair
题面
Description
给定一个正整数 n n n,一共有 n n n座龙门,跳过第 j ( j < n ) j (j<n) j(j<n)座龙门将会到达第 j + 1 j+1 j+1座龙门前,特殊地,跳过第 n n n座龙门后将会到达第 1 1 1 座龙门前。
胖头鱼一开始在第一座龙门前,接下来,第 i i i个时刻内它会向前跳 i i i次,每次跳过 1 1 1座龙门,求最小的正整数 x x x满足第 x x x个时刻结束后胖头鱼恰好会回到起点。
Input
第一行一个整数
T
T
T,表示数据组数。
接下来
T
T
T行,每行一个整数
n
n
n,表示一共有
n
n
n座龙门。
1 ≤ T ≤ 100 1 \\le T \\le 100 1≤T≤100, 1 ≤ n ≤ 1 0 12 1 \\le n \\le 10^{12} 1≤n≤1012
Output
一共 T T T行,每行一个整数 x x x,表示答案。
样例1
样例输入 1
5
2
4
6
8
10
样例输出 1
3
7
3
15
4
样例解释 1
对
n
=
10
n=10
n=10的样例解释:
一开始在
1
1
1的前面也就是位置
0
0
0,
第一时刻跳一步到
(
0
+
1
)
m
o
d
n
=
1
(0+1) ~ mod ~ n = 1
(0+1) mod n=1,
第二时刻跳两步到
(
1
+
2
)
m
o
d
n
=
3
(1+2) ~mod ~ n = 3
(1+2) mod n=3,
第三时刻跳三步到
(
3
+
3
)
m
o
d
n
=
6
(3+3) ~mod ~ n = 6
(3+3) mod n=6,
第四时刻跳四步到
(
6
+
4
)
m
o
d
n
=
0
(6+4) ~ mod ~ n = 0
(6+4) mod n=0,
第四时刻后恰好跳回原点
0
0
0,所以答案为
4
4
4。
样例2
样例输入 2
10
200479710
1041705379
766770747
257088468
877586977
86834214
757618747
884911150
388001368
494728090
样例输出 2
30464759
9427197
74899308
9020648
877586976
43417107
96416647
212378675
43718463
36697240
解题思路
一开始想岔了(因为数论太烂),把想法写的贼牛的样子(式子貌似也写错了(((()
∑
i
=
1
x
i
≡
0
(
m
o
d
n
)
{\\sum_{i=1}^{x}i}\\equiv 0(mod\\ n)
i=1∑xi≡0(mod n)
x即
后面才发现这个式子是可以简化的,
n
∣
(
x
(
x
+
1
)
/
2
)
→
2
n
∣
x
(
x
+
1
)
n|(x(x+1) / 2)\\rightarrow 2n|x(x+1)
n∣(x(x+1)/2)→2n∣x(x+1)
设
a
∣
2
n
,
b
=
2
n
/
a
a|2n,b=2n/a
a∣2n,b=2n/a,则(
a
b
=
2
n
ab=2n
ab=2n)
a
b
∣
x
(
x
+
1
)
ab|x(x+1)
ab∣x(x+1)
a
p
⋅
b
q
=
x
(
x
+
1
)
ap·bq=x(x+1)
ap⋅bq=x(x+1),设
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
引用扩展欧几里得,
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b)
套上去就是
a
x
+
b
y
=
1
ax+by=1
ax+by=1(-号可以算进系数y中),用扩欧求解
这就产生一个条件了,
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1(即a,b互质),于是就可以先处理出2n的质因子
#tips
感谢LTH大爷 (虽然还是看不懂)
Code
#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
const ll INF = 1e18;
ll n, ans, f[maxn + 100], p[maxn + 100];
int num, T;
void init() {
f[0] = f[1] = 1;
for(int i = 2; i <= maxn; i++) {
if(!f[i]) p[++num] = i;
for(int j = 1; j <= num && i * p[j] <= maxn; j++) {
f[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
}
void demo(ll n) {
f[0] = 0;
for(int i = 1; i <= num && p[i] <= n; i++) {
if(n % p[i] == 0)
f[++f[0]] = 1;
while(n % p[i] == 0){n /= p[i], f[f[0]] *= p[i];}
}
if(n > 1)
f[++f[0]] = n;
}
void work(ll a, ll b, ll &x, ll &y) { //ex_gcd
if(b == 0) {x = 1, y = 0; return;}
work(b, a % b, x, y);
ll t = x;
x = y, y = t - (a / b) * y;
}
void dfs(int now, ll a, ll b) {
if(now == f[0] + 1) {
ll x, y;
work(a, b, x, y);
y = -y % a;
if(y <= 0) y += a;
ans = min(ans, y * b);
return;
}
dfs(now + 1, a * f[now], b);
dfs(now + 1, a, b * f[now]);
}
int main() {
init(); //把质数处理出来
scanf("%d", &T);
while(T--) {
scanf("%lld", &n);
n *= 2;
demo(n); //把2n的质因数求出来
ans = INF;
dfs(1, 1, 1); //dfs出a,b的可能性,找到最小的解
printf("%lld\\n", ans);
}
}
以上是关于jzoj7177质因数分解扩展欧几里得鱼跃龙门的主要内容,如果未能解决你的问题,请参考以下文章