結果
問題 | No.950 行列累乗 |
ユーザー | chocorusk |
提出日時 | 2019-12-13 04:42:31 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 56 ms / 2,000 ms |
コード長 | 4,408 bytes |
コンパイル時間 | 1,466 ms |
コンパイル使用メモリ | 130,428 KB |
実行使用メモリ | 8,384 KB |
最終ジャッジ日時 | 2024-06-27 03:51:31 |
合計ジャッジ時間 | 4,112 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 13 ms
6,816 KB |
testcase_01 | AC | 17 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 23 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | AC | 2 ms
6,944 KB |
testcase_09 | AC | 2 ms
6,944 KB |
testcase_10 | AC | 2 ms
6,944 KB |
testcase_11 | AC | 2 ms
6,940 KB |
testcase_12 | AC | 2 ms
6,944 KB |
testcase_13 | AC | 2 ms
6,940 KB |
testcase_14 | AC | 2 ms
6,940 KB |
testcase_15 | AC | 2 ms
6,940 KB |
testcase_16 | AC | 2 ms
6,944 KB |
testcase_17 | AC | 2 ms
6,940 KB |
testcase_18 | AC | 2 ms
6,944 KB |
testcase_19 | AC | 2 ms
6,948 KB |
testcase_20 | AC | 2 ms
6,944 KB |
testcase_21 | AC | 23 ms
6,940 KB |
testcase_22 | AC | 33 ms
6,944 KB |
testcase_23 | AC | 25 ms
6,944 KB |
testcase_24 | AC | 33 ms
6,940 KB |
testcase_25 | AC | 20 ms
6,940 KB |
testcase_26 | AC | 28 ms
6,976 KB |
testcase_27 | AC | 15 ms
6,944 KB |
testcase_28 | AC | 31 ms
6,940 KB |
testcase_29 | AC | 28 ms
6,940 KB |
testcase_30 | AC | 38 ms
6,944 KB |
testcase_31 | AC | 31 ms
6,940 KB |
testcase_32 | AC | 40 ms
8,116 KB |
testcase_33 | AC | 39 ms
6,940 KB |
testcase_34 | AC | 34 ms
6,944 KB |
testcase_35 | AC | 34 ms
6,940 KB |
testcase_36 | AC | 14 ms
6,940 KB |
testcase_37 | AC | 11 ms
6,944 KB |
testcase_38 | AC | 11 ms
6,944 KB |
testcase_39 | AC | 15 ms
6,944 KB |
testcase_40 | AC | 35 ms
8,256 KB |
testcase_41 | AC | 34 ms
8,252 KB |
testcase_42 | AC | 24 ms
6,944 KB |
testcase_43 | AC | 44 ms
8,384 KB |
testcase_44 | AC | 36 ms
7,100 KB |
testcase_45 | AC | 56 ms
8,256 KB |
testcase_46 | AC | 49 ms
7,232 KB |
testcase_47 | AC | 1 ms
6,940 KB |
testcase_48 | AC | 37 ms
7,116 KB |
testcase_49 | AC | 47 ms
8,240 KB |
testcase_50 | AC | 54 ms
8,236 KB |
testcase_51 | AC | 55 ms
8,256 KB |
testcase_52 | AC | 24 ms
6,940 KB |
testcase_53 | AC | 24 ms
6,940 KB |
testcase_54 | AC | 2 ms
6,944 KB |
testcase_55 | AC | 2 ms
6,940 KB |
testcase_56 | AC | 15 ms
6,940 KB |
testcase_57 | AC | 2 ms
6,944 KB |
testcase_58 | AC | 1 ms
6,944 KB |
testcase_59 | AC | 18 ms
6,944 KB |
testcase_60 | AC | 14 ms
6,940 KB |
ソースコード
#include <cstdio> #include <cstring> #include <iostream> #include <string> #include <cmath> #include <bitset> #include <vector> #include <map> #include <set> #include <queue> #include <deque> #include <algorithm> #include <complex> #include <unordered_map> #include <unordered_set> #include <random> #include <cassert> #include <fstream> #include <utility> #include <functional> #include <time.h> #include <stack> #include <array> #define popcount __builtin_popcount using namespace std; typedef long long int ll; typedef pair<ll, int> P; ll p; using arr=array<ll, 2>; using Mat=array<arr, 2>; Mat matmul(Mat a, Mat b){ Mat c={}; for(int i=0; i<2; i++){ for(int j=0; j<2; j++){ for(int k=0; k<2; k++){ (c[i][j]+=a[i][k]*b[k][j])%=p; } } } return c; } Mat matpow(Mat a, ll k){ Mat ap=a, ans={}; ans[0][0]=ans[1][1]=1; while(k){ if(k&1) ans=matmul(ap, ans); ap=matmul(ap, ap); k>>=1; } return ans; } Mat e, ainv; bool nuee; ll matlog(Mat a, Mat b, ll d){ ll sq=1; while(sq*sq<d) sq++; vector<pair<Mat, int>> vp(sq); vp[0]=make_pair(e, 0); for(int i=1; i<sq; i++){ vp[i]=make_pair(matmul(vp[i-1].first, a), i); } auto cp=[](pair<Mat, int> x, pair<Mat, int> y){ for(int i=0; i<2; i++){ for(int j=0; j<2; j++){ if(x.first[i][j]!=y.first[i][j]) return x.first[i][j]<y.first[i][j]; } } return x.second<y.second; }; sort(vp.begin(), vp.end(), cp); Mat ap=matpow(ainv, sq); for(int i=0; i<sq; i++){ int t=lower_bound(vp.begin(), vp.end(), make_pair(b, 0), cp)-vp.begin(); if(t<sq && vp[t].first==b){ if(i*sq+vp[t].second<d){ if(i==0 && vp[t].second==0){ nuee=1; if(t+1<sq && vp[t].first==vp[t+1].first) return vp[t+1].second; }else{ return i*sq+vp[t].second; } } } b=matmul(b, ap); } return -1; } ll gcd(ll a, ll b){ if(b==0) return a; return gcd(b, a%b); } ll powmod(ll a, ll k, ll mod){ ll ap=a, ans=1; while(k){ if(k&1){ ans*=ap; ans%=mod; } ap=ap*ap; ap%=mod; k>>=1; } return ans; } ll inv(ll a, ll m){ ll b=m, x=1, y=0; while(b>0){ ll t=a/b; swap(a-=t*b, b); swap(x-=t*y, y); } return (x%m+m)%m; } ll discretelog(ll x, ll y, ll m){ ll p=1%m; for(int i=0; i<=30; i++){ if(p==y) return i; (p*=x)%=m; } ll g=gcd(x, m); ll m1=m; for(ll i=2; i*i<=g; i++){ if(g%i==0){ while(g%i==0) g/=i; while(m1%i==0) m1/=i; } } if(g>1){ while(m1%g==0) m1/=g; } if(y%(m/m1)!=0) return -1; x%=m1, y%=m1; ll d=1; while(d*d<m1) d++; ll invx=inv(x, m1); unordered_map<ll, ll> mp; //yx^(-b) ll y1=y; for(ll i=0; i<d; i++){ mp[y1]=i; (y1*=invx)%=m1; if(y1==y) break; } ll xd=powmod(x, d, m1); ll q=1%m1; for(ll i=0; i<d; i++){ auto itr=mp.find(q); if(itr!=mp.end()){ return i*d+itr->second; } (q*=xd)%=m1; } return -1; } ll order(ll a){ if(a==1) return 1; return discretelog(a, inv(a, p), p)+1; } int main() { cin>>p; Mat a, b; cin>>a[0][0]>>a[0][1]>>a[1][0]>>a[1][1]>>b[0][0]>>b[0][1]>>b[1][0]>>b[1][1]; if(a==b){ cout<<1<<endl; return 0; } Mat a2=matmul(a, a); if(a2==b){ cout<<2<<endl; return 0; } if(a2[0][0]==0 && a2[0][1]==0 && a2[1][0]==0 && a2[1][1]==0){ cout<<-1<<endl; return 0; } ll ad=(a[0][0]*a[1][1]-a[0][1]*a[1][0]%p+p)%p, bd=(b[0][0]*b[1][1]-b[0][1]*b[1][0]%p+p)%p; if(ad==0){ e=matpow(a, p-1), ainv=matpow(a, p-2); ll n=matlog(a, b, p); if(n==-1){ cout<<-1<<endl; return 0; } if(matpow(a, n)==b) cout<<n<<endl; else cout<<-1<<endl; return 0; }else{ e[0][0]=e[1][1]=1; if(matpow(a, p*p-1)==e) ainv=matpow(a, p*p-2); else ainv=matpow(a, p*(p-1)-1); } ll r=discretelog(ad, bd, p), m=order(ad); if(r==-1){ cout<<-1<<endl; return 0; } Mat ap=matpow(a, m), c=matmul(b, matpow(ainv, r)); ainv=matpow(ainv, m); nuee=0; ll q=matlog(ap, c, 2*p); if(q==-1){ cout<<-1<<endl; return 0; } if(nuee && r>0) q=0; if(matpow(a, q*m+r)==b) cout<<q*m+r<<endl; else cout<<-1<<endl; return 0; }