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

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

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

658閲覧

AOJ <JOI - Prelim 0590> 総当りではTLEになるがループ条件を変えるだけでACになる理由が分からない

mjk

総合スコア303

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/08/09 17:22

状況説明

問題:AOJ <JOI - Prelim 0590>

この問題を自力では解けなくてネットで検索したところサンプルコードの解答例を見つけました。
解法のヒントの数式の部分を読んで自力で実装(総当り?)して入力例で正解だったので提出したところ、
TLE(Time Limit Exceeded)になりました。

その後詳しく見比べるとforループ文の終了回数の部分( i*i<=S と i<=s )が違いました。
試しに自作のコードのそこだけを修正して提出したところAC(Accepted)となりました。
(9秒以上掛かったものが1秒以下になりました)

//AC(正解) for(int i=1;i*i<=S;i++) //TLE(時間切れ) for(int i=1;i<=s;i++)

知りたいこと

結果と数式から計算量が大きく減ることは明らかなのですが、
何故forループ文の終了回数の部分( i<=s )を( i*i<=S )とするのかがよく分かりません。
数学的なことかアルゴリズム的な明快な理由があるはずだとは思うのですがアドバイス頂ければ助かります。

解答例

引用元tobiasの日記

C++

1#include<iostream> 2#include<cmath> 3 4using namespace std; 5 6bool is_room(int S){ 7 8 for(int i=1;i*i<=S;i++) 9 if((S-i)%(2*i+1)==0)return true; 10 return false; 11} 12 13int main(void){ 14 15 int n,S,cnt=0; 16 17 cin >> n; 18 while(n--){ 19 cin >> S; 20 if(!is_room(S))cnt++; 21 } 22 cout << cnt << endl; 23 24 return 0; 25}

補足情報(開発環境など)

Win10
VSC1.47.3
C++14
gcc version 8.2.0 (Rev3, Built by MSYS2 project)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

部屋の面積2xy+x+yは、xとyについて対称です。
よって、(x, y) = (a, b)の時に部屋の面積として成立するなら、
xとyを入れ替えた(x, y) = (b, a)の時も成立することになります。
実際、LDと洋室を90°回転し、キッチンと玄関の図形を入れ替えれば、
面積がそのままでxとyが入れ替わった部屋を作ることができます。

したがって、x <= yの場合に限定して考えてよいことになります。
そのxとyの大小関係がどこで入れ替わるか、ですが、
例えば部屋の面積がxyであれば、√Sを境にして大小が入れ替わることになります。
今回の場合、xyが部屋の面積のほぼ半分であることを考えれば、およそ√(S/2)あたりで入れ替わることが推測できます。この正確なところは私には詰め切れませんが(※追記で詰めました)、√Sより手前の時点で大小が入れ替わることは確実なので、i*i<=Sまでの範囲を調べれば十分という事になります。

数学的に詰めます。
2xy+x+y=Sという方程式を考えると、これは
(2x+1)(2y+1)=2S+1と同値になります。
2x+1<=2y+1で考えればよいので、
2x+1<=√(2S+1)、ということでやはり、おおよそ
x<=(√2/2)√Sくらいの範囲まで考えれば十分となります。

なお、2x+1,2y+1はともに3以上の奇数、2S+1は奇数なので、
「2S+1が9以上で、合成数である」と捉えることもできます。

投稿2020/08/09 18:31

編集2020/08/10 03:21
swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mjk

2020/08/09 21:15

なるほど! X=10,Y=10,S=100で想像してみたらスカっとしました! 大小が入れ替わるのは10なので√100=10,10*10,i*i<=S が直感で理解出来ました。 ありがとうございました。本当にスッキリしました!
mjk

2020/08/10 05:48

x<=(√2/2)√S が導かれるなら、(√2/2)√S<√Sなのでi*i<=Sの本題の式で十分カバー出来ていることが一目瞭然ですね。 自力で数式を変形させても√Sに辿り着け無かったので本当に感謝です。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問