SRM302 div1 easy
とりあえずキューで実装してみたが、2s以内ではできない.
int countOperations(int N, int M) { int flag[M+1]; memset(flag, -1, sizeof flag); queueQ; Q.push(N); flag[N] = 0; while( !Q.empty() ) { int n = Q.front(); Q.pop(); if(n > M) continue; for(int i = n/2; i >= 2; i--) { if(n % i == 0 && n+i <= M) { if(flag[n+i] == -1) { flag[n+i] = flag[n] + 1; Q.push(n+i); } //ここが原因か? もしかすると、if(flag[n+i] == -1)というとこをいじくればいいかも. } } //end for } return flag[M]; }
深さ優先検索でしようとすると、1)で死亡してしまう.
bool DivisorInc::go(int n) { if(n == m) { return true; } else { for(int i = n/2; i >= 2; i--) { if(n % i == 0 && n+i <= && flag[i+n] == -1) { flag[n+i] = flag[n]+1; if(go(n+i)) return true; } } } return false; }
素数を絡めてDPでとくと2)で引っかかる.
int countOperations(int N, int M) { fill(flag, flag+100002, INF); flag[N] = 0; vectorprime = getPrime(M); int sz = prime.size(); for(int i = N; i < M; i++) { if(flag[i] != INF) { for(int j = 0; j < sz && prime[j]*prime[j] <= i; j++) { int tmp = prime[j]; if(i % tmp == 0) { if(i+tmp <= M) { flag[ i+tmp ] = min(flag[i+tmp], flag[i]+1); } if(i+i/tmp <= M) { flag[i + i/tmp ] = min(flag[i + i/tmp], flag[i]+1); } } } //end for j } } //end for i return flag[M] == INF ? -1 : flag[M]; } };
深く考えずに、順番にやっていくのが正解.
int countOperations(int N, int M) {
fill(flag, flag+100002, INF);
flag[N] = 0;
for(int i = N; i < M; i++) {
if(flag[i] != INF) {
for(int j = 2; j*j <= i; j++) {
if(i % j == 0) {
if(i+j <= M) {
flag[ i+j ] = min(flag[i+j], flag[i]+1);
}
if(i+i/j <= M) {
flag[i + i/j ] = min(flag[i + i/j], flag[i]+1);
}
}
} //end for j
}
} //end for i
return flag[M] == INF ? -1 : flag[M];
}
};
//queueで実装しようとしてもどのみちdpは必要.本質的にはなんの変わりもない.