QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#281130 | #1482. Pisano Periods | neko_nyaa | 100 ✓ | 157ms | 3708kb | C++20 | 4.3kb | 2023-12-09 21:32:13 | 2023-12-09 21:32:14 |
Judging History
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