結果
| 問題 |
No.261 ぐるぐるぐるぐる!あみだくじ!
|
| コンテスト | |
| ユーザー |
koyumeishi
|
| 提出日時 | 2015-06-30 17:59:56 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.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;
}
}
koyumeishi