さて、Preblem C。ここまでは余裕だったが、これはどうだろう。
問題文曰く、
Do you ever become frustrated with television because you keep seeing the same things, recycled over and over again? Well I personally don't care about television, but I do sometimes feel that way about numbers.だそうだが、個人的には筆者の方が変態だと思う。
C++のSTLからsetを使う。Pair型の<演算子も定義する。(n, m)でnの方が優先。
recycleはnのstartから後ろを前に持ってきた数字を返す。
あとはひたすら全通り試していく。
ひたすらsetにinsertしても重複しないから便利。
でもって表示はsize()メソッドで表示すればfor文カウントもせずに終了できる。
コード全文は以下。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#define IN_RANGE(x, A, B) ((A <= x)&&(x <= B))
typedef struct _pair{
unsigned int n;
unsigned int m;
} Pair;
bool operator<(const Pair& a, const Pair& b) {
if(a.n == b.n) return a.m < b.m;
else return a.n < b.n;
}
unsigned int NUMBER_OF_DIGITS;
int recycle(const unsigned int n, const unsigned int start) {
unsigned int div_base = pow(10, start), temp = n % div_base;
return (n / div_base) + (temp * pow(10, NUMBER_OF_DIGITS - start));
}
int main(int argc, char** argv) {
unsigned int T, A, B, i, n, k, m;
//FILE *fp = fopen("input.txt", "r");
//FILE *fp = fopen("C-small-attempt0.in", "r");
FILE *fp = fopen("C-large.in", "r");
fscanf(fp, "%d", &T);
for(i=0; i<T; ++i) {
fscanf(fp, "%d %d", &A, &B);
NUMBER_OF_DIGITS = log10(A)+1;
if(NUMBER_OF_DIGITS == 1) {
printf("Case #%d: %d\n", i+1, 0);
continue;
}
std::set<Pair> pairs;
for(n=A; n<=B; ++n) {
for(k=1; k<NUMBER_OF_DIGITS; ++k) {
m = recycle(n, k);
if(n == m) continue;
Pair new_pair = ((n < m) ? (Pair){n, m} : (Pair){m, n});
if(IN_RANGE(m, A, B))
pairs.insert(new_pair);
}
}
printf("Case #%d: %d\n", i+1, pairs.size());
}
fclose(fp);
return EXIT_SUCCESS;
}
意外と楽だったかな。
0 件のコメント:
コメントを投稿