結果
問題 | No.261 ぐるぐるぐるぐる!あみだくじ! |
ユーザー | koyumeishi |
提出日時 | 2015-06-30 17:59:56 |
言語 | C++11 (gcc 11.4.0) |
結果 |
CE
(最新)
AC
(最初)
|
実行時間 | - |
コード長 | 3,497 bytes |
コンパイル時間 | 600 ms |
コンパイル使用メモリ | 60,400 KB |
最終ジャッジ日時 | 2024-11-14 19:05:31 |
合計ジャッジ時間 | 1,195 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
コンパイルメッセージ
main.cpp: In function ‘std::vector<int> get_order(int, std::vector<int>&)’: main.cpp:100:9: error: ‘iota’ was not declared in this scope 100 | iota(a.begin(), a.end(), 0); | ^~~~ main.cpp: In function ‘int main()’: main.cpp:122:9: error: ‘iota’ was not declared in this scope 122 | iota(v.begin(), v.end(), 0); | ^~~~
ソースコード
#include <iostream> #include <vector> #include <algorithm> using namespace std; long long gcd(long long a, long long b){ if(b==0) return a; return gcd(b, a%b); } long long lcm(long long a, long long b){ if(a<b) swap(a,b); if(b==1) return a; return a * (b/gcd(a,b)); } long long extgcd(long long a, long long b, long long &x, long long &y){ long long d=a; if(b!=0){ d = extgcd(b, a%b, y, x); y -= (a/b) * x; }else{ x = 1; y = 0; } return d; } long long mod_inverse(long long a, long long m){ long long x,y; extgcd(a,m,x,y); return (m+x%m)%m; } // Z % Yi = Xi であるようなZを求める。Garnerのアルゴリズム O(N^2) // 参考 http://techtipshoge.blogspot.jp/2015/02/blog-post_15.html // http://yukicoder.me/problems/448 long long Chinese_Remainder_Theorem_Garner(vector<long long> x, vector<long long> y){ int N = x.size(); bool valid = true; //前処理 //gcd(Yi,Yj) == 1 (i!=j) でなくてはならないので、 //共通の因数 g = gcd(Yi,Yj) を見つけたら片側に寄せてしまう for(int i=0; i<N; i++){ for(int j=i+1; j<N; j++){ if(i == j) continue; long long g = gcd(y[i], y[j]); if( x[i]%g != x[j]%g ) valid = false; //解が存在しない if(g != 1){ y[i] /= g; y[j] /= g; long long g_ = gcd(y[i], g); while(g_ != 1){ y[i] *= g_; g /= g_; g_ = gcd(y[i], g); } y[j] *= g; x[i] %= y[i]; x[j] %= y[j]; } } } if(!valid){ cerr << -1 << endl; return -1; } //Garner's algorithm vector<long long> z(N); for(int i=0; i<N; i++){ z[i] = x[i]; for(int j=0; j<i; j++){ z[i] = mod_inverse(y[j], y[i]) % y[i] * (z[i] - z[j]) % y[i]; z[i] = (z[i]+y[i])%y[i]; } } long long ans = 0; long long tmp = 1; for(int i=0; i<N; i++){ ans = (ans + z[i] * tmp)/*%MOD*/; tmp = (tmp * y[i])/*%MOD*/; } return ans; } //巡回群 v の部分群の位数を得る vector<int> get_order(int n, vector<int>& v){ vector<int> a(n), b(n, 114514); iota(a.begin(), a.end(), 0); for(int i=0; i<n; i++){ auto tmp = a; for(int j=0; j<n; j++){ tmp[j] = a[v[j]]; } swap(tmp, a); for(int j=0; j<n; j++){ if(a[j] == j){ b[j] = min(b[j], i+1); } } } return b; } int main(){ int n,k; cin >> n >> k; vector<int> v(n); iota(v.begin(), v.end(), 0); for(int i=0; i<k; i++){ int x,y; cin >> x >> y; x--; y--; swap(v[x], v[y]); } vector<int> orders = get_order(n, v); long long M = 1; //vの位数 for(int i=0; i<n; i++){ M = lcm(M, orders[i]); } int q; cin >> q; while(q--){ vector<int> w(n); for(int i=0; i<n; i++){ cin >> w[i]; w[i]--; } vector<int> a(n), b(n, 114514); iota(a.begin(), a.end(), 0); for(int i=0; i<n; i++){ auto tmp = a; for(int j=0; j<n; j++){ tmp[j] = a[v[j]]; } swap(tmp, a); for(int j=0; j<n; j++){ if(a[j] == w[j]){ b[j] = min(b[j], i+1); } } } vector<long long> x, y; bool valid = true; vector<bool> visit(n, false); for(int i=0; i<n; i++){ if(visit[i]) continue; int pos = i; int val = b[i]; if(b[i] == 114514){ valid = false; break; } while(visit[pos] == false){ visit[pos] = true; if(val != b[pos]){ valid = false; break; } pos = v[pos]; } x.push_back(val); y.push_back(orders[i]); } if(valid == false){ cout << -1 << endl; continue; } long long ans = Chinese_Remainder_Theorem_Garner(x,y); if(ans == 0) ans = M; cout << ans << endl; } }