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

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

新規登録して質問してみよう
ただいま回答率
85.31%
C

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

Q&A

解決済

1回答

3455閲覧

ディリクレの算術級数定理(ICPCの過去問題)

Taka787

総合スコア23

C

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

0グッド

0クリップ

投稿2019/07/28 12:16

ICPCの過去問題ですが、以下の仕様を1秒以内に実行を行いたいです。
現在は1秒を超えています。
どのようにすればよろしいでしょうか?

こんばんは,選手諸君. a と d が互いに素な正の整数ならば, a から始まり d ずつ増える 等差数列 a, a + d, a + 2d, a + 3d, a + 4d, ... には無限個の素数が含まれる. このことはディリクレの算術級数定理として知られている. ガウス(Johann Carl Friedrich Gauss, 1777 - 1855)が予想していたことを, 1837年に ディリクレ(Johann Peter Gustav Lejeune Dirichlet, 1805 - 1859)が 証明した. たとえば, 2から始まり3ずつ増える等差数列 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, ... は,無限個の素数 2, 5, 11, 17, 23, 29, 41, 47, 53, 59, 71, 83, 89, ... を含む. そこで君の使命だが, 与えられた正整数 a と d と n に対して, この等差数列に含まれる n 番目の素数を求めるプログラムを書くことにある. 例によって,君もしくは君の仲間が疲れはて,あるいは混乱しても,当局はいっさい関知しないからそのつもりで. なお,この審判システムは3時間で自動的に停止する.成功を祈る.

C

1 2#include <stdio.h> 3 4int sosu(int n){ 5//素数判定関数 6 int i; 7 8 if(n < 2) 9 return 0; 10 //もしnが2より小さい場合、0を返す。 11 12 if(n == 2) 13 return 1; 14 //もしnが2だった場合、1を返す 15 for(i = 2; i <= n/2; i++){ 16 if(n%i == 0) 17 return 0; 18 //もし、nがほかの数(i)で割り切れたら素数ではないので、0を返す。 19 } 20 21 return 1; 22 //素数であるときのみ1を返す。 23} 24 25int main(int argc, char *argv[]){ 26 27 int a, d, n; 28 //初項a、公差d、n番目の素数 それぞれの変数を宣言。 29 while(1){ 30 //標準入力がある限りループを回す。 31 scanf("%d %d %d", &a, &d, &n); 32 //標準入力で、初項a、公差d、n番目の素数を読み取る。 33 34 if(a == 0 && d == 0 && n == 0){ 35 //もし、標準入力に「0 0 0」が来たら、終了。 36 break; 37 } 38 39 int m = a; 40 //mには、初期値に初項aを代入。 41 int count = 0; 42 //countには初期値を設定。 43 44 while(1){ 45 46 if(sosu(m)){ 47 //素数判定 48 count++; 49 } 50 51 if(count == n){ 52 //もし、n番目の素数にたどり着いた場合 53 printf("%d\n", m); 54 //標準出力で素数表示。 55 break; 56 } 57 58 m += d; 59 //mに公差dを足していく。 60 } 61 } 62 63 64 return 0; 65}

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

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

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

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

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

guest

回答1

0

ベストアンサー

a, d, n の値により、また実行環境により時間は違うので、一概にどうすれば一秒切れるかというのは言えません。

for(i = 2; i <= n/2; i++){

とりあえずここは無駄が多いですね。
たとえば n が 100 の場合、i は 50 までカウントアップされますが、10 まででいいはずです。100 を 10 で割ると 10 で、これ以上 i を増やすと、割った商は 10 未満、つまり既に確かめた値になります。
条件は i <= n/2 ではなく、i * i <= n にしましょう。

投稿2019/07/28 13:09

Zuishin

総合スコア28673

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

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

Taka787

2019/07/28 13:25

とても分かりやすい説明でした。ありがとうございました。ちょっとしたところを変えるだけで、結構実行時間が変わることがわかりました。とても勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問