質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • C

    3678questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

x以下の最大のべき数を求めたい

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 164

BONERer

score 11

イメージ説明

 前提・実現したいこと

https://beta.atcoder.jp/contests/abc097/tasks/abc097_b
この問題を解きたいです。
自分で考えた添付の画像通りに沿ってコードを書きました。
最初の条件分岐ですがb!=1をb==1に直していますが
そのほかは大きな変更はありません。

 発生している問題・エラーメッセージ

コンパイルエラーは出ていませんが
x=1,2のとき以外はどこかでループしていてプログラムが終わらず
x=2のときでもまともな答えが出ません。

 該当のソースコード

#include<stdio.h>
//b^pを計算する関数
int myCalc(int b, int p)
{
  int i = 1;

  while(i <= p-1){
    b=b*b;
  }

  return b;
}

int main(void)
{
  int x=0, b=1, p;
  int max=1;

  scanf("%d", &x);

  for(;;){
    p=1;
    if(b==1){
      if(x==myCalc(b, p)){
        printf("1\n");
        return 0;
      }else{
        b++;
        printf("b:%d\n", b);
      }
    }
    printf("stop\n");
    while(x > myCalc(b, p)){
      p++;
      printf("p:%d", p);
    }
    if(p!=1){
      if(myCalc(b, p) > max) max = myCalc(b, p);
      b++;
      printf("b:%d\n", b);
    }else{
      printf("%d\n", max);
      return 0;
    }
    printf("***\n");
  }
}

 試したこと

プリントデバッグで、stopまでしか表示されないことがわかりました。
理由がわかりません。

 補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

stopまでしか出ないということは、次のwhileループ内のprintfは出力されないということですね。
ということはwhileループの条件で呼んでいるmyClac関数が戻ってこないということです。
myCalc関数を見るとまたwhileループしていますが、ループ条件に使用しているipがループ内で変動していません。
よってここで無限ループになっているのではないでしょうか。
ここ↓

  while(i <= p-1){
    b=b*b;
  }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/05 17:49

    回答ありがとうございます。
    いわれてみればたしかにmyCalcで止まってる以外
    考えられませんでしたね。。。
    ありがとうございました。
    さっさと完成させます。

    キャンセル

+2

まず、myCalcの時点で間違っています。b = b * b;とすると、繰り返すたびに2乗、2乗で増えていくので、「bのp乗」にはなりません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/05 17:51

    回答ありがとうございます。
    bを固定するために別のにコピーする必要がありましたね。。
    たとえば
    i=b;
    for(j=1; j<=p-1; j++){
    b=b*j;
    }
    だとできました。
    ありがとうございました。

    キャンセル

  • 2018/06/06 01:13

    そこは j ではなく i を掛けるべきなのでは…。

    キャンセル

  • 2018/06/06 06:50

    回答ありがとうございます。す。
    ご指摘ありがとうございます(iで固定した意味)

    キャンセル

checkベストアンサー

+1

こんにちは、原因の方はほかの方の回答にあるのでここでは別解を言いたいと思います。
参考になったら幸いです。
ソースを見た感じ少しfor文の中が複雑になっているのでもっと簡潔にできないかなぁと思いました。

まず例の10の時ですが、10に最も近いべき乗数を求めるとき底の最大値は√10の整数部分の3となり、そこから指数部分を2から1ずつ増やし10を超えないべき乗数まで算出します。

 なぜ底の最大値は平方根の整数部分なのか

べき乗数の指数部分の最小値は2です。つまり、底が平方根の指数部分を超えると入力した値より大きいべき乗数が出ます。例の10の時、例えば4のべき乗を考えると4^2 > 10となり計算する必要はありません。
つまり、底が3以下の場合のべき乗数で10以下のものだけを考えればいいことになります。

 話を戻します。

実際に、計算すると
2^2 = 4 , 2^3 = 8 (2^4 = 16は10を超えるので底が2のループは終了)
3^2 = 9, (3^3 = 27は10を超えるので底が3のループは終了)

となり、最大値は9となります。べき乗数を求め、より大きいものが出るとき最大値が更新するようにします。これを2重for文でやればいいです。

int answer = 1;

for(i = 2; pow(i,2) <= n; i++){
    for(j = 2; pow(i,j) <= n; j++){
        if(answer <= pow(i,j)){
            answer = pow(i,j);
        }
    }
}

printf("%d\n",answer);


for文の条件文のところに <=と イコールを付けることで入力した数値がべき乗数の時も対応しています。
また、入力した数値が1の時ですが、このときはまずfor文を通らないので初期値answer = 1が答えとなります。

 ちなみに

私も最初はaのb乗を求める関数を自分で作ってました。しかし、C言語には<math.h>をインクルードすると
pow関数を使うことができます。pow(a,b)はaのb乗を表しています。
詳しくはpow関数をご覧ください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/05 22:11

    書いたソースコードを全部載せようかとおもいましたが 全部載せると当サイトの規約に反するかもしれないので重要なところだけをピックアップしました。(もし全部載せていいのなら全部載せますが....)

    キャンセル

  • 2018/06/06 08:15

    回答ありがとうございます。
    xの整数部をAとしたとき、A<=ルートx<A+1となって
    何乗してもルートx<A+1という関係が変わらない、というのを利用して
    pow(i, 2) <= nとされているところになるほどと思いました。
    教えていただいたやり方を参考にして完成できました。
    丁寧な回答ありがとうございました。

    キャンセル

  • 2018/06/06 09:24

    べき乗数は底、指数部分ともに2以上なのでjの初期値は2でした。すみません。その部分を訂正しました。

    キャンセル

  • 2018/06/06 09:25 編集

    そうですね。for(i = 2; pow(i,2) <= n; i++)で、底のiが2から入力した整数の整数部分以下を動き、
    for(j = 2; pow(i,j) <= n; j++)で、指数部分jが2から「iのj乗がnを超えない」数値まで動き
    最大値を求めていく感じです。
    お役に立ってうれしいです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3678questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。