桁数判定はx
とは別の変数xtemp
に移してやったほうがいいと思います。
x
を書き換えられると不都合なためです。
また, digit
は桁数計算の前に初期化する必要があります。
intだと桁数が余裕で足りないので、long longにしました。
ですが、それでもn>18の場合にはオーバーフローして正しい答えが出ませんので、n>18の答えも正しく出したい時には多倍長整数の計算が必要になります。
C
1#include <stdio.h>
2
3int main(void) {
4 long long n;
5 scanf("%lld", &n);
6 long long x = 1LL;
7
8 for (long long i = 0; i < 1000; i++) {
9 x = x * 3LL;
10
11 long long xtemp = x;
12 long long digit = 0;
13
14 while (xtemp != 0) { // xの桁数を計算
15 xtemp /= 10LL;
16 ++digit;
17 }
18
19 if (digit > n) {
20 break;
21 }
22 }
23 printf("%lld\n", x/3LL); //最後nよりも1桁多い最小のxだから割る3
24 return 0;
25}
私の実装例
#include <assert.h>
#include <stdio.h>
int main(void)
{
long long n;
scanf("%lld", &n);
if (n <= 0 || n >= 18) {
printf("範囲外です");
return 0;
}
long long end_ndigit = 1;
for (long long i = 0; i < n; i++) {
end_ndigit *= 10LL;
}
long long x = 1LL;
while (x < end_ndigit) {
x *= 3LL;
}
printf("%lld\n", x / 3LL); //最後nよりも1桁多い最小のxだから割る3
return 0;
}
GNU MPで組んでみました
C
1#include <gmp.h>
2#include <stdio.h>
3
4int main(void)
5{
6 long long n;
7 scanf("%lld", &n);
8 if(n<=0){
9 printf("n must be positive.\n");
10 return 0;
11 }
12 // 10**nを計算しておく
13 mpz_t end_ndigit;
14 mpz_init(end_ndigit);
15 mpz_set_ui(end_ndigit, 1);
16 for (long long i = 0; i < n; i++) {
17 mpz_mul_ui(end_ndigit, end_ndigit, 10);
18 }
19
20 // 3をかけ続け, 桁数がnを超えたら抜ける
21 mpz_t x;
22 mpz_init(x);
23 mpz_set_ui(x, 1);
24 while (mpz_cmp(x, end_ndigit) < 0) {
25 mpz_mul_ui(x, x, 3);
26 }
27
28 // 答え
29 mpz_cdiv_q_ui(x, x, 3);
30 gmp_printf("%Zd\n", x);
31
32 // 解放
33 mpz_clear(x);
34 mpz_clear(end_ndigit);
35 return 0;
36}
text
180
247780373265559358009192445772039644256794138579444188363337645975725833060824587
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/29 17:44
2020/07/31 01:45
2020/07/31 04:03