結果
| 問題 |
No.1013 〇マス進む
|
| コンテスト | |
| ユーザー |
otamay6
|
| 提出日時 | 2019-11-08 16:43:51 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,411 bytes |
| コンパイル時間 | 2,293 ms |
| コンパイル使用メモリ | 187,108 KB |
| 実行使用メモリ | 9,280 KB |
| 最終ジャッジ日時 | 2024-09-15 04:26:30 |
| 合計ジャッジ時間 | 10,587 ms |
|
ジャッジサーバーID (参考情報) |
judge6 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 49 WA * 13 |
ソースコード
/*under Implementation
K回の試行で閉じたサイクルにたどり着かない場合があり、これをO(N)で計算する実装ができてない
*/
#include<bits/stdc++.h>
#include<unistd.h>
#define REP(i,n) for(int i=0,i##_len=(n);i<i##_len;++i)
#define rep(i,a,b) for(int i=int(a);i<int(b);++i)
#define All(x) (x).begin(),(x).end()
#define DEBUG(x) cerr<<(x)<<endl
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int MAX_N=100010;
ll N,K;
vector<ll> p;
vector<P> incycle;//(何番目の閉じたサイクル内にいるか,サイクルの何処に位置するか)
vector<P> tocycle;//(閉じたサイクルのどの数字に最初に当たるか、そこまでの長さ)
vector<int> tocnt;//閉じたサイクルに行くまでの手数
vector<vector<P>> cycle;//(サイクルのk番目のP上での位置、スタート地点から何個P同士の境界を越えたか)
vector<bool> outcycle;
void rsz(){
p.resize(N);
incycle.resize(N);
tocycle.resize(N);
tocnt.resize(N);
outcycle.resize(N,false);
}
void cycle_detection(){
vector<bool> used(N,false);
vector<int> prev(N,-1);
int k=1;
REP(i,N){
if(used[i]||incycle[i].first!=-1||prev[i]!=-1) continue;
int j=i,pre=-1;
bool out=false;
while(!used[j]){
used[j]=true;
prev[j]=pre;
pre=j;
j+=p[j];
j%=N;
if(incycle[j].first!=-1||outcycle[j]){
out=true;
break;
}
}
if(out) {//サイクルに合流する数字は別に計算する
for(int v=pre;v!=-1;v=prev[v]){
outcycle[v]=true;
}
continue;
}
cycle.resize(k+1);
int u = pre, t = 0, num = 0;
while(u!=j){
u=prev[u];
}
for(int v=prev[u];v!=-1;v=prev[v]){
outcycle[v]=true;
}
do{
cycle[k].push_back(P(u,t));
incycle[u] = P(k,num);
u+=p[u];
if(u>=N){
u-=N;
t++;
}
num++;
}while(u!=j);
k++;
}
}
P outcycle_calculate(int i){
if(incycle[i].first!=-1){
return P(i,0);
}
if(tocycle[i].first!=-1){
return tocycle[i];
}
P res=outcycle_calculate((i+p[i])%N);
tocnt[i]=tocnt[(i+p[i])%N]+1;
return tocycle[i]=P(res.first,res.second+p[i]);
}
P Ans_calculate(int start){
ll res=start;
ll remain=K;
if(incycle[res].first==-1){
remain-=tocnt[res];
res+=tocycle[res].second;
}
if(remain>0){
int C = incycle[res%N].first, num=incycle[res%N].second;
ll LtoF = (cycle[C].back().first>=cycle[C][0].first);
ll clen = N*(cycle[C].back().second + LtoF );
ll csz = cycle[C].size();
res += clen*(remain/csz);
remain%=csz;
int last=(num+remain)%csz;
if(last<num){
ll border = cycle[C].back().second - cycle[C][num].second -1 + LtoF + cycle[C][last].second;
if(border!=-1){
res += N - cycle[C][num].first
+ N*border
+ cycle[C][last].first;
}
else{
res += cycle[C][last].first - cycle[C][num].first;
}
}
else{
ll border = cycle[C][last].second - cycle[C][num].second -1;
if(border!=-1){
res += N - cycle[C][num].first
+ N*border
+ cycle[C][last].first;
}
else{
res += cycle[C][last].first - cycle[C][num].first;
}
}
remain=0;
}
return P(res+1,remain);
}
int main(){
cin>>N>>K;
rsz();
REP(i,N){
cin>>p[i];
incycle[i] = P(-1,-1);
tocycle[i] = P(-1,-1);
if(p[i]==N){
incycle[i] = P(0,0);
cycle.push_back({P(i,0)});
}
}
cycle_detection();
//REP(i,cycle.size()) REP(j,cycle[i].size()) cerr<<cycle[i][j].first<<" \n"[j==cycle[i].size()-1];
REP(i,N){
outcycle_calculate(i);
//cout<<i<<endl<<tocycle[i].first<<" "<<tocycle[i].second<<endl;
}
vector<P> ans(N);
REP(i,N) ans[i]=Ans_calculate(i);
REP(i,N) cout<<ans[i].first<<endl;
}
otamay6