QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#281130#1482. Pisano Periodsneko_nyaa100 ✓157ms3708kbC++204.3kb2023-12-09 21:32:132023-12-09 21:32:14

Judging History

你现在查看的是最新测评结果

  • [2023-12-09 21:32:14]
  • 评测
  • 测评结果:100
  • 用时:157ms
  • 内存:3708kb
  • [2023-12-09 21:32:13]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
template <typename T> using min_heap = priority_queue<T, vector<T>, greater<T>>;

/******* MISC ********/
void print128(__int128 n) {
	if (n == 0) {
		cout << "0\n";
		return;
	}
	if (n < 0) {
		cout << "-";
		n *= -1;
	}
	string ans;
	while (n) {
		ans.push_back('0' + n%10);
		n /= 10;
	}
	reverse(ans.begin(), ans.end());
	cout << ans << '\n';
}

/******* MATH ********/
typedef unsigned long long ull;
ull modmul(ull a, ull b, ull M) {
	ll ret = a * b - M * ull(1.L / M * a * b);
	return ret + M * (ret < 0) - M * (ret >= (ll)M);
}
ull modpow(ull b, ull e, ull mod) {
	ull ans = 1;
	for (; e; b = modmul(b, b, mod), e /= 2)
		if (e & 1) ans = modmul(ans, b, mod);
	return ans;
}

/******* POLLARD RHO ********/
bool isPrime(ull n) {
	if (n < 2 || n % 6 % 4 != 1) return (n | 1) == 3;
	ull A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022},
		s = __builtin_ctzll(n-1), d = n >> s;
	for (ull a : A) {   // ^ count trailing zeroes
		ull p = modpow(a%n, d, n), i = s;
		while (p != 1 && p != n - 1 && a % n && i--)
			p = modmul(p, p, n);
		if (p != n-1 && i != s) return 0;
	}
	return 1;
}
ull pollard(ull n) {
	ull x = 0, y = 0, t = 30, prd = 2, i = 1, q;
	auto f = [&](ull x) { return modmul(x, x, n) + i; };
	while (t++ % 40 || __gcd(prd, n) == 1) {
		if (x == y) x = ++i, y = f(x);
		if ((q = modmul(prd, max(x,y) - min(x,y), n))) prd = q;
		x = f(x), y = f(f(y));
	}
	return __gcd(prd, n);
}
vector<ull> factor(ull n) {
	if (n == 1) return {};
	if (isPrime(n)) return {n};
	ull x = pollard(n);
	auto l = factor(x), r = factor(n / x);
	l.insert(l.end(), all(r));
	return l;
}

/******* FIBONACCI TEST ********/

typedef vector<ll> Poly;
ll linearRec(Poly S, Poly tr, ll k, ll mod) {
	int n = sz(tr);

	auto combine = [&](Poly a, Poly b) {
		Poly res(n * 2 + 1);
		rep(i,0,n+1) rep(j,0,n+1)
			res[i + j] = (res[i+j] + modmul(a[i], b[j], mod)) % mod;
		for (int i = 2 * n; i > n; --i) rep(j,0,n)
			res[i - 1 - j] = (res[i - 1 - j] + modmul(res[i], tr[j], mod)) % mod;
		res.resize(n + 1);
		return res;
	};

	Poly pol(n + 1), e(pol);
	pol[0] = e[1] = 1;

	for (++k; k; k /= 2) {
		if (k % 2) pol = combine(pol, e);
		e = combine(e, e);
	}

	ll res = 0;
	rep(i,0,n) res = (res + modmul(pol[i + 1], S[i], mod)) % mod;
	return res;
}

ll fibmod(ll n, ll m) {
    return linearRec({0, 1}, {1, 1}, n+1, m);
}

// is p a valid period of modulo m?
mt19937 rng(time(NULL));
const int TEST_CNT = 10;
bool isPeriodic(ll m, ll p) {
    rep(i,0,TEST_CNT) {
        ll g = abs((int)rng()) % p;
        if (fibmod(g, m) != fibmod(g+p, m)) return 0;
		if (fibmod(g, m) != fibmod(g+2*p, m)) return 0;
		if (fibmod(g, m) != fibmod(g+3*p, m)) return 0;
    }
    return 1;
}

/******* SOLUTION ********/

// pisano period of fibonacci mod p, p is prime
ll solvePrime(ll p) {
    if (p == 2) return 3;
    if (p == 3) return 8;
    if (p == 5) return 20;

    ll cand;
    if (p%5 == 1 || p%5 == 4) cand = p-1;
    else cand = 2*(p+1);

    // pisano period is any divisor of cand
    vector<ull> ft = factor(cand);
    ll ans = cand;
    
	for (ull i: ft) {
		if (isPeriodic(p, ans/i)) ans /= i;
	}
    return ans;
}

// pisano period of fibonacci mod p^q, p is prime
ll solvePrimePower(ll p, ll q) {
    ll kp = solvePrime(p);
    ll m = 1;
    rep(i,0,q) m *= p;

    // pisano period is a divisor of p^(q-1) * kp
    for (int i = 0; i <= q; i++) {
        if (isPeriodic(m, kp)) return kp;
        kp *= p;
    }
    return kp;
}

__int128 ggcd(__int128 a, __int128 b){ 
	while (a&&b)a>b?a%=b:b%=a; 
	return a+b; 
} 
 
__int128 llcm(__int128 a, __int128 b){ 
	return a/ggcd(a,b)*b; 
}

void solve() {
    string trash; cin >> trash;
    ll m; cin >> m;
    vector<ull> f = factor(m);
    map<ull, int> mp;
    for (ull i: f) mp[i]++;

    __int128 ans = 1;
    for (auto [p, q]: mp) {
        ans = llcm(ans, solvePrimePower(p, q));
    }
    cout << trash << ' ';
    print128(ans);
}

signed main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t = 1; cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 157ms
memory: 3708kb

input:

1000
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
16 17
17 18
18 19
19 20
20 21
21 22
22 23
23 24
24 25
25 26
26 27
27 28
28 29
29 30
30 31
31 32
32 33
33 34
34 35
35 36
36 37
37 38
38 39
39 40
40 41
41 42
42 43
43 44
44 45
45 46
46 47
47 48
48 49
49 50
50 51
51 52
52 53
...

output:

1 3
2 8
3 6
4 20
5 24
6 16
7 12
8 24
9 60
10 10
11 24
12 28
13 48
14 40
15 24
16 36
17 24
18 18
19 60
20 16
21 30
22 48
23 24
24 100
25 84
26 72
27 48
28 14
29 120
30 30
31 48
32 40
33 36
34 80
35 24
36 76
37 18
38 56
39 60
40 40
41 48
42 88
43 30
44 120
45 48
46 32
47 24
48 112
49 300
50 72
51 84
5...

result:

ok 1000 lines